avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
8
u-boot/post/drivers/Makefile
Normal file
8
u-boot/post/drivers/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# (C) Copyright 2002-2006
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
obj-y += flash.o i2c.o memory.o rtc.o
|
||||
107
u-boot/post/drivers/flash.c
Normal file
107
u-boot/post/drivers/flash.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Parallel NOR Flash tests
|
||||
*
|
||||
* Copyright (c) 2005-2011 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <post.h>
|
||||
#include <flash.h>
|
||||
|
||||
#if CONFIG_POST & CONFIG_SYS_POST_FLASH
|
||||
|
||||
/*
|
||||
* This code will walk over the declared sectors erasing them,
|
||||
* then programming them, then verifying the written contents.
|
||||
* Possible future work:
|
||||
* - verify sectors before/after are not erased/written
|
||||
* - verify partial writes (e.g. programming only middle of sector)
|
||||
* - verify the contents of the erased sector
|
||||
* - better seed pattern than 0x00..0xff
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SYS_POST_FLASH_NUM
|
||||
# define CONFIG_SYS_POST_FLASH_NUM 0
|
||||
#endif
|
||||
#if CONFIG_SYS_POST_FLASH_START >= CONFIG_SYS_POST_FLASH_END
|
||||
# error "invalid flash block start/end"
|
||||
#endif
|
||||
|
||||
extern flash_info_t flash_info[];
|
||||
|
||||
static void *seed_src_data(void *ptr, ulong *old_len, ulong new_len)
|
||||
{
|
||||
unsigned char *p;
|
||||
ulong i;
|
||||
|
||||
p = ptr = realloc(ptr, new_len);
|
||||
if (!ptr)
|
||||
return ptr;
|
||||
|
||||
for (i = *old_len; i < new_len; ++i)
|
||||
p[i] = i;
|
||||
|
||||
*old_len = new_len;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int flash_post_test(int flags)
|
||||
{
|
||||
ulong len;
|
||||
void *src;
|
||||
int ret, n, n_start, n_end;
|
||||
flash_info_t *info;
|
||||
|
||||
/* the output from the common flash layers needs help */
|
||||
puts("\n");
|
||||
|
||||
len = 0;
|
||||
src = NULL;
|
||||
info = &flash_info[CONFIG_SYS_POST_FLASH_NUM];
|
||||
n_start = CONFIG_SYS_POST_FLASH_START;
|
||||
n_end = CONFIG_SYS_POST_FLASH_END;
|
||||
|
||||
for (n = n_start; n < n_end; ++n) {
|
||||
ulong s_start, s_len, s_off;
|
||||
|
||||
s_start = info->start[n];
|
||||
s_len = flash_sector_size(info, n);
|
||||
s_off = s_start - info->start[0];
|
||||
|
||||
src = seed_src_data(src, &len, s_len);
|
||||
if (!src) {
|
||||
printf("malloc(%#lx) failed\n", s_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\tsector %i: %#lx +%#lx", n, s_start, s_len);
|
||||
|
||||
ret = flash_erase(info, n, n + 1);
|
||||
if (ret) {
|
||||
flash_perror(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = write_buff(info, src, s_start, s_len);
|
||||
if (ret) {
|
||||
flash_perror(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = memcmp(src, (void *)s_start, s_len);
|
||||
if (ret) {
|
||||
printf(" verify failed with %i\n", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(src);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
97
u-boot/post/drivers/i2c.c
Normal file
97
u-boot/post/drivers/i2c.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* I2C test
|
||||
*
|
||||
* For verifying the I2C bus, a full I2C bus scanning is performed.
|
||||
*
|
||||
* #ifdef CONFIG_SYS_POST_I2C_ADDRS
|
||||
* The test is considered as passed if all the devices and only the devices
|
||||
* in the list are found.
|
||||
* #ifdef CONFIG_SYS_POST_I2C_IGNORES
|
||||
* Ignore devices listed in CONFIG_SYS_POST_I2C_IGNORES. These devices
|
||||
* are optional or not vital to board functionality.
|
||||
* #endif
|
||||
* #else [ ! CONFIG_SYS_POST_I2C_ADDRS ]
|
||||
* The test is considered as passed if any I2C device is found.
|
||||
* #endif
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <post.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#if CONFIG_POST & CONFIG_SYS_POST_I2C
|
||||
|
||||
static int i2c_ignore_device(unsigned int chip)
|
||||
{
|
||||
#ifdef CONFIG_SYS_POST_I2C_IGNORES
|
||||
const unsigned char i2c_ignore_list[] = CONFIG_SYS_POST_I2C_IGNORES;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(i2c_ignore_list); i++)
|
||||
if (i2c_ignore_list[i] == chip)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_post_test (int flags)
|
||||
{
|
||||
unsigned int i;
|
||||
#ifndef CONFIG_SYS_POST_I2C_ADDRS
|
||||
/* Start at address 1, address 0 is the general call address */
|
||||
for (i = 1; i < 128; i++) {
|
||||
if (i2c_ignore_device(i))
|
||||
continue;
|
||||
if (i2c_probe (i) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No devices found */
|
||||
return -1;
|
||||
#else
|
||||
unsigned int ret = 0;
|
||||
int j;
|
||||
unsigned char i2c_addr_list[] = CONFIG_SYS_POST_I2C_ADDRS;
|
||||
|
||||
/* Start at address 1, address 0 is the general call address */
|
||||
for (i = 1; i < 128; i++) {
|
||||
if (i2c_ignore_device(i))
|
||||
continue;
|
||||
if (i2c_probe(i) != 0)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < sizeof(i2c_addr_list); ++j) {
|
||||
if (i == i2c_addr_list[j]) {
|
||||
i2c_addr_list[j] = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == sizeof(i2c_addr_list)) {
|
||||
ret = -1;
|
||||
post_log("I2C: addr %02x not expected\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(i2c_addr_list); ++i) {
|
||||
if (i2c_addr_list[i] == 0xff)
|
||||
continue;
|
||||
if (i2c_ignore_device(i2c_addr_list[i]))
|
||||
continue;
|
||||
post_log("I2C: addr %02x did not respond\n", i2c_addr_list[i]);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_POST & CONFIG_SYS_POST_I2C */
|
||||
550
u-boot/post/drivers/memory.c
Normal file
550
u-boot/post/drivers/memory.c
Normal file
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/* Memory test
|
||||
*
|
||||
* General observations:
|
||||
* o The recommended test sequence is to test the data lines: if they are
|
||||
* broken, nothing else will work properly. Then test the address
|
||||
* lines. Finally, test the cells in the memory now that the test
|
||||
* program knows that the address and data lines work properly.
|
||||
* This sequence also helps isolate and identify what is faulty.
|
||||
*
|
||||
* o For the address line test, it is a good idea to use the base
|
||||
* address of the lowest memory location, which causes a '1' bit to
|
||||
* walk through a field of zeros on the address lines and the highest
|
||||
* memory location, which causes a '0' bit to walk through a field of
|
||||
* '1's on the address line.
|
||||
*
|
||||
* o Floating buses can fool memory tests if the test routine writes
|
||||
* a value and then reads it back immediately. The problem is, the
|
||||
* write will charge the residual capacitance on the data bus so the
|
||||
* bus retains its state briefely. When the test program reads the
|
||||
* value back immediately, the capacitance of the bus can allow it
|
||||
* to read back what was written, even though the memory circuitry
|
||||
* is broken. To avoid this, the test program should write a test
|
||||
* pattern to the target location, write a different pattern elsewhere
|
||||
* to charge the residual capacitance in a differnt manner, then read
|
||||
* the target location back.
|
||||
*
|
||||
* o Always read the target location EXACTLY ONCE and save it in a local
|
||||
* variable. The problem with reading the target location more than
|
||||
* once is that the second and subsequent reads may work properly,
|
||||
* resulting in a failed test that tells the poor technician that
|
||||
* "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which
|
||||
* doesn't help him one bit and causes puzzled phone calls. Been there,
|
||||
* done that.
|
||||
*
|
||||
* Data line test:
|
||||
* ---------------
|
||||
* This tests data lines for shorts and opens by forcing adjacent data
|
||||
* to opposite states. Because the data lines could be routed in an
|
||||
* arbitrary manner the must ensure test patterns ensure that every case
|
||||
* is tested. By using the following series of binary patterns every
|
||||
* combination of adjacent bits is test regardless of routing.
|
||||
*
|
||||
* ...101010101010101010101010
|
||||
* ...110011001100110011001100
|
||||
* ...111100001111000011110000
|
||||
* ...111111110000000011111111
|
||||
*
|
||||
* Carrying this out, gives us six hex patterns as follows:
|
||||
*
|
||||
* 0xaaaaaaaaaaaaaaaa
|
||||
* 0xcccccccccccccccc
|
||||
* 0xf0f0f0f0f0f0f0f0
|
||||
* 0xff00ff00ff00ff00
|
||||
* 0xffff0000ffff0000
|
||||
* 0xffffffff00000000
|
||||
*
|
||||
* To test for short and opens to other signals on our boards, we
|
||||
* simply test with the 1's complemnt of the paterns as well, resulting
|
||||
* in twelve patterns total.
|
||||
*
|
||||
* After writing a test pattern. a special pattern 0x0123456789ABCDEF is
|
||||
* written to a different address in case the data lines are floating.
|
||||
* Thus, if a byte lane fails, you will see part of the special
|
||||
* pattern in that byte lane when the test runs. For example, if the
|
||||
* xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa
|
||||
* (for the 'a' test pattern).
|
||||
*
|
||||
* Address line test:
|
||||
* ------------------
|
||||
* This function performs a test to verify that all the address lines
|
||||
* hooked up to the RAM work properly. If there is an address line
|
||||
* fault, it usually shows up as two different locations in the address
|
||||
* map (related by the faulty address line) mapping to one physical
|
||||
* memory storage location. The artifact that shows up is writing to
|
||||
* the first location "changes" the second location.
|
||||
*
|
||||
* To test all address lines, we start with the given base address and
|
||||
* xor the address with a '1' bit to flip one address line. For each
|
||||
* test, we shift the '1' bit left to test the next address line.
|
||||
*
|
||||
* In the actual code, we start with address sizeof(ulong) since our
|
||||
* test pattern we use is a ulong and thus, if we tried to test lower
|
||||
* order address bits, it wouldn't work because our pattern would
|
||||
* overwrite itself.
|
||||
*
|
||||
* Example for a 4 bit address space with the base at 0000:
|
||||
* 0000 <- base
|
||||
* 0001 <- test 1
|
||||
* 0010 <- test 2
|
||||
* 0100 <- test 3
|
||||
* 1000 <- test 4
|
||||
* Example for a 4 bit address space with the base at 0010:
|
||||
* 0010 <- base
|
||||
* 0011 <- test 1
|
||||
* 0000 <- (below the base address, skipped)
|
||||
* 0110 <- test 2
|
||||
* 1010 <- test 3
|
||||
*
|
||||
* The test locations are successively tested to make sure that they are
|
||||
* not "mirrored" onto the base address due to a faulty address line.
|
||||
* Note that the base and each test location are related by one address
|
||||
* line flipped. Note that the base address need not be all zeros.
|
||||
*
|
||||
* Memory tests 1-4:
|
||||
* -----------------
|
||||
* These tests verify RAM using sequential writes and reads
|
||||
* to/from RAM. There are several test cases that use different patterns to
|
||||
* verify RAM. Each test case fills a region of RAM with one pattern and
|
||||
* then reads the region back and compares its contents with the pattern.
|
||||
* The following patterns are used:
|
||||
*
|
||||
* 1a) zero pattern (0x00000000)
|
||||
* 1b) negative pattern (0xffffffff)
|
||||
* 1c) checkerboard pattern (0x55555555)
|
||||
* 1d) checkerboard pattern (0xaaaaaaaa)
|
||||
* 2) bit-flip pattern ((1 << (offset % 32))
|
||||
* 3) address pattern (offset)
|
||||
* 4) address pattern (~offset)
|
||||
*
|
||||
* Being run in normal mode, the test verifies only small 4Kb
|
||||
* regions of RAM around each 1Mb boundary. For example, for 64Mb
|
||||
* RAM the following areas are verified: 0x00000000-0x00000800,
|
||||
* 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800-
|
||||
* 0x04000000. If the test is run in slow-test mode, it verifies
|
||||
* the whole RAM.
|
||||
*/
|
||||
|
||||
#include <post.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
#if CONFIG_POST & (CONFIG_SYS_POST_MEMORY | CONFIG_SYS_POST_MEM_REGIONS)
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* Define INJECT_*_ERRORS for testing error detection in the presence of
|
||||
* _good_ hardware.
|
||||
*/
|
||||
#undef INJECT_DATA_ERRORS
|
||||
#undef INJECT_ADDRESS_ERRORS
|
||||
|
||||
#ifdef INJECT_DATA_ERRORS
|
||||
#warning "Injecting data line errors for testing purposes"
|
||||
#endif
|
||||
|
||||
#ifdef INJECT_ADDRESS_ERRORS
|
||||
#warning "Injecting address line errors for testing purposes"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This function performs a double word move from the data at
|
||||
* the source pointer to the location at the destination pointer.
|
||||
* This is helpful for testing memory on processors which have a 64 bit
|
||||
* wide data bus.
|
||||
*
|
||||
* On those PowerPC with FPU, use assembly and a floating point move:
|
||||
* this does a 64 bit move.
|
||||
*
|
||||
* For other processors, let the compiler generate the best code it can.
|
||||
*/
|
||||
static void move64(const unsigned long long *src, unsigned long long *dest)
|
||||
{
|
||||
#if defined(CONFIG_MPC8260)
|
||||
asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */
|
||||
"stfd 0, 0(4)" /* *dest = fpr0 */
|
||||
: : : "fr0" ); /* Clobbers fr0 */
|
||||
return;
|
||||
#else
|
||||
*dest = *src;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This is 64 bit wide test patterns. Note that they reside in ROM
|
||||
* (which presumably works) and the tests write them to RAM which may
|
||||
* not work.
|
||||
*
|
||||
* The "otherpattern" is written to drive the data bus to values other
|
||||
* than the test pattern. This is for detecting floating bus lines.
|
||||
*
|
||||
*/
|
||||
const static unsigned long long pattern[] = {
|
||||
0xaaaaaaaaaaaaaaaaULL,
|
||||
0xccccccccccccccccULL,
|
||||
0xf0f0f0f0f0f0f0f0ULL,
|
||||
0xff00ff00ff00ff00ULL,
|
||||
0xffff0000ffff0000ULL,
|
||||
0xffffffff00000000ULL,
|
||||
0x00000000ffffffffULL,
|
||||
0x0000ffff0000ffffULL,
|
||||
0x00ff00ff00ff00ffULL,
|
||||
0x0f0f0f0f0f0f0f0fULL,
|
||||
0x3333333333333333ULL,
|
||||
0x5555555555555555ULL
|
||||
};
|
||||
const unsigned long long otherpattern = 0x0123456789abcdefULL;
|
||||
|
||||
|
||||
static int memory_post_dataline(unsigned long long * pmem)
|
||||
{
|
||||
unsigned long long temp64 = 0;
|
||||
int num_patterns = ARRAY_SIZE(pattern);
|
||||
int i;
|
||||
unsigned int hi, lo, pathi, patlo;
|
||||
int ret = 0;
|
||||
|
||||
for ( i = 0; i < num_patterns; i++) {
|
||||
move64(&(pattern[i]), pmem++);
|
||||
/*
|
||||
* Put a different pattern on the data lines: otherwise they
|
||||
* may float long enough to read back what we wrote.
|
||||
*/
|
||||
move64(&otherpattern, pmem--);
|
||||
move64(pmem, &temp64);
|
||||
|
||||
#ifdef INJECT_DATA_ERRORS
|
||||
temp64 ^= 0x00008000;
|
||||
#endif
|
||||
|
||||
if (temp64 != pattern[i]){
|
||||
pathi = (pattern[i]>>32) & 0xffffffff;
|
||||
patlo = pattern[i] & 0xffffffff;
|
||||
|
||||
hi = (temp64>>32) & 0xffffffff;
|
||||
lo = temp64 & 0xffffffff;
|
||||
|
||||
post_log("Memory (date line) error at %08x, "
|
||||
"wrote %08x%08x, read %08x%08x !\n",
|
||||
pmem, pathi, patlo, hi, lo);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size)
|
||||
{
|
||||
ulong *target;
|
||||
ulong *end;
|
||||
ulong readback;
|
||||
ulong xor;
|
||||
int ret = 0;
|
||||
|
||||
end = (ulong *)((ulong)base + size); /* pointer arith! */
|
||||
xor = 0;
|
||||
for(xor = sizeof(ulong); xor > 0; xor <<= 1) {
|
||||
target = (ulong *)((ulong)testaddr ^ xor);
|
||||
if((target >= base) && (target < end)) {
|
||||
*testaddr = ~*target;
|
||||
readback = *target;
|
||||
|
||||
#ifdef INJECT_ADDRESS_ERRORS
|
||||
if(xor == 0x00008000) {
|
||||
readback = *testaddr;
|
||||
}
|
||||
#endif
|
||||
if(readback == *testaddr) {
|
||||
post_log("Memory (address line) error at %08x<->%08x, "
|
||||
"XOR value %08x !\n",
|
||||
testaddr, target, xor);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_test1(unsigned long start,
|
||||
unsigned long size,
|
||||
unsigned long val)
|
||||
{
|
||||
unsigned long i;
|
||||
ulong *mem = (ulong *) start;
|
||||
ulong readback;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong); i++) {
|
||||
mem[i] = val;
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
|
||||
readback = mem[i];
|
||||
if (readback != val) {
|
||||
post_log("Memory error at %08x, "
|
||||
"wrote %08x, read %08x !\n",
|
||||
mem + i, val, readback);
|
||||
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_test2(unsigned long start, unsigned long size)
|
||||
{
|
||||
unsigned long i;
|
||||
ulong *mem = (ulong *) start;
|
||||
ulong readback;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong); i++) {
|
||||
mem[i] = 1 << (i % 32);
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
|
||||
readback = mem[i];
|
||||
if (readback != (1 << (i % 32))) {
|
||||
post_log("Memory error at %08x, "
|
||||
"wrote %08x, read %08x !\n",
|
||||
mem + i, 1 << (i % 32), readback);
|
||||
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_test3(unsigned long start, unsigned long size)
|
||||
{
|
||||
unsigned long i;
|
||||
ulong *mem = (ulong *) start;
|
||||
ulong readback;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong); i++) {
|
||||
mem[i] = i;
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
|
||||
readback = mem[i];
|
||||
if (readback != i) {
|
||||
post_log("Memory error at %08x, "
|
||||
"wrote %08x, read %08x !\n",
|
||||
mem + i, i, readback);
|
||||
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_test4(unsigned long start, unsigned long size)
|
||||
{
|
||||
unsigned long i;
|
||||
ulong *mem = (ulong *) start;
|
||||
ulong readback;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong); i++) {
|
||||
mem[i] = ~i;
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
for (i = 0; i < size / sizeof (ulong) && !ret; i++) {
|
||||
readback = mem[i];
|
||||
if (readback != ~i) {
|
||||
post_log("Memory error at %08x, "
|
||||
"wrote %08x, read %08x !\n",
|
||||
mem + i, ~i, readback);
|
||||
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (i % 1024 == 0)
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_test_lines(unsigned long start, unsigned long size)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = memory_post_dataline((unsigned long long *)start);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_addrline((ulong *)start, (ulong *)start,
|
||||
size);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_addrline((ulong *)(start+size-8),
|
||||
(ulong *)start, size);
|
||||
WATCHDOG_RESET();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_test_patterns(unsigned long start, unsigned long size)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = memory_post_test1(start, size, 0x00000000);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_test1(start, size, 0xffffffff);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_test1(start, size, 0x55555555);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_test1(start, size, 0xaaaaaaaa);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_test2(start, size);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_test3(start, size);
|
||||
WATCHDOG_RESET();
|
||||
if (!ret)
|
||||
ret = memory_post_test4(start, size);
|
||||
WATCHDOG_RESET();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_test_regions(unsigned long start, unsigned long size)
|
||||
{
|
||||
unsigned long i;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < (size >> 20) && (!ret); i++) {
|
||||
if (!ret)
|
||||
ret = memory_post_test_patterns(start + (i << 20),
|
||||
0x800);
|
||||
if (!ret)
|
||||
ret = memory_post_test_patterns(start + (i << 20) +
|
||||
0xff800, 0x800);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int memory_post_tests(unsigned long start, unsigned long size)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = memory_post_test_lines(start, size);
|
||||
if (!ret)
|
||||
ret = memory_post_test_patterns(start, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* !! this is only valid, if you have contiguous memory banks !!
|
||||
*/
|
||||
__attribute__((weak))
|
||||
int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
|
||||
{
|
||||
bd_t *bd = gd->bd;
|
||||
|
||||
*vstart = CONFIG_SYS_SDRAM_BASE;
|
||||
*size = (gd->ram_size >= 256 << 20 ?
|
||||
256 << 20 : gd->ram_size) - (1 << 20);
|
||||
|
||||
/* Limit area to be tested with the board info struct */
|
||||
if ((*vstart) + (*size) > (ulong)bd)
|
||||
*size = (ulong)bd - *vstart;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void arch_memory_failure_handle(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int memory_regions_post_test(int flags)
|
||||
{
|
||||
int ret = 0;
|
||||
phys_addr_t phys_offset = 0;
|
||||
u32 memsize, vstart;
|
||||
|
||||
arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
|
||||
|
||||
ret = memory_post_test_lines(vstart, memsize);
|
||||
if (!ret)
|
||||
ret = memory_post_test_regions(vstart, memsize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int memory_post_test(int flags)
|
||||
{
|
||||
int ret = 0;
|
||||
phys_addr_t phys_offset = 0;
|
||||
u32 memsize, vstart;
|
||||
|
||||
arch_memory_test_prepare(&vstart, &memsize, &phys_offset);
|
||||
|
||||
do {
|
||||
if (flags & POST_SLOWTEST) {
|
||||
ret = memory_post_tests(vstart, memsize);
|
||||
} else { /* POST_NORMAL */
|
||||
ret = memory_post_test_regions(vstart, memsize);
|
||||
}
|
||||
} while (!ret &&
|
||||
!arch_memory_test_advance(&vstart, &memsize, &phys_offset));
|
||||
|
||||
arch_memory_test_cleanup(&vstart, &memsize, &phys_offset);
|
||||
if (ret)
|
||||
arch_memory_failure_handle();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_POST&(CONFIG_SYS_POST_MEMORY|CONFIG_SYS_POST_MEM_REGIONS) */
|
||||
193
u-boot/post/drivers/rtc.c
Normal file
193
u-boot/post/drivers/rtc.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
/*
|
||||
* RTC test
|
||||
*
|
||||
* The Real Time Clock (RTC) operation is verified by this test.
|
||||
* The following features are verified:
|
||||
* o) RTC Power Fault
|
||||
* This is verified by analyzing the rtc_get() return status.
|
||||
* o) Time uniformity
|
||||
* This is verified by reading RTC in polling within
|
||||
* a short period of time.
|
||||
* o) Passing month boundaries
|
||||
* This is checked by setting RTC to a second before
|
||||
* a month boundary and reading it after its passing the
|
||||
* boundary. The test is performed for both leap- and
|
||||
* nonleap-years.
|
||||
*/
|
||||
|
||||
#include <post.h>
|
||||
#include <rtc.h>
|
||||
|
||||
#if CONFIG_POST & CONFIG_SYS_POST_RTC
|
||||
|
||||
static int rtc_post_skip (ulong * diff)
|
||||
{
|
||||
struct rtc_time tm1;
|
||||
struct rtc_time tm2;
|
||||
ulong start1;
|
||||
ulong start2;
|
||||
|
||||
rtc_get (&tm1);
|
||||
start1 = get_timer (0);
|
||||
|
||||
while (1) {
|
||||
rtc_get (&tm2);
|
||||
start2 = get_timer (0);
|
||||
if (tm1.tm_sec != tm2.tm_sec)
|
||||
break;
|
||||
if (start2 - start1 > 1500)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tm1.tm_sec != tm2.tm_sec) {
|
||||
*diff = start2 - start1;
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
|
||||
{
|
||||
time_t t = rtc_mktime(tm) + sec;
|
||||
struct rtc_time ntm;
|
||||
|
||||
rtc_to_tm(t, &ntm);
|
||||
|
||||
rtc_set (&ntm);
|
||||
}
|
||||
|
||||
int rtc_post_test (int flags)
|
||||
{
|
||||
ulong diff;
|
||||
unsigned int i;
|
||||
struct rtc_time svtm;
|
||||
static unsigned int daysnl[] =
|
||||
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
static unsigned int daysl[] =
|
||||
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
unsigned int ynl = 1999;
|
||||
unsigned int yl = 2000;
|
||||
unsigned int skipped = 0;
|
||||
int reliable;
|
||||
|
||||
/* Time reliability */
|
||||
reliable = rtc_get (&svtm);
|
||||
|
||||
/* Time uniformity */
|
||||
if (rtc_post_skip (&diff) != 0) {
|
||||
post_log ("Timeout while waiting for a new second !\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (rtc_post_skip (&diff) != 0) {
|
||||
post_log ("Timeout while waiting for a new second !\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (diff < 950 || diff > 1050) {
|
||||
post_log ("Invalid second duration !\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Passing month boundaries */
|
||||
|
||||
if (rtc_post_skip (&diff) != 0) {
|
||||
post_log ("Timeout while waiting for a new second !\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
rtc_get (&svtm);
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
time_t t;
|
||||
struct rtc_time tm;
|
||||
|
||||
tm.tm_year = ynl;
|
||||
tm.tm_mon = i + 1;
|
||||
tm.tm_mday = daysnl[i];
|
||||
tm.tm_hour = 23;
|
||||
tm.tm_min = 59;
|
||||
tm.tm_sec = 59;
|
||||
t = rtc_mktime(&tm);
|
||||
rtc_to_tm(t, &tm);
|
||||
rtc_set (&tm);
|
||||
|
||||
skipped++;
|
||||
if (rtc_post_skip (&diff) != 0) {
|
||||
rtc_post_restore (&svtm, skipped);
|
||||
post_log ("Timeout while waiting for a new second !\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtc_get (&tm);
|
||||
if (tm.tm_mon == i + 1) {
|
||||
rtc_post_restore (&svtm, skipped);
|
||||
post_log ("Month %d boundary is not passed !\n", i + 1);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
time_t t;
|
||||
struct rtc_time tm;
|
||||
|
||||
tm.tm_year = yl;
|
||||
tm.tm_mon = i + 1;
|
||||
tm.tm_mday = daysl[i];
|
||||
tm.tm_hour = 23;
|
||||
tm.tm_min = 59;
|
||||
tm.tm_sec = 59;
|
||||
t = rtc_mktime(&tm);
|
||||
|
||||
rtc_to_tm(t, &tm);
|
||||
rtc_set (&tm);
|
||||
|
||||
skipped++;
|
||||
if (rtc_post_skip (&diff) != 0) {
|
||||
rtc_post_restore (&svtm, skipped);
|
||||
post_log ("Timeout while waiting for a new second !\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtc_get (&tm);
|
||||
if (tm.tm_mon == i + 1) {
|
||||
rtc_post_restore (&svtm, skipped);
|
||||
post_log ("Month %d boundary is not passed !\n", i + 1);
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
rtc_post_restore (&svtm, skipped);
|
||||
|
||||
/* If come here, then RTC operates correcty, check the correctness
|
||||
* of the time it reports.
|
||||
*/
|
||||
if (reliable < 0) {
|
||||
post_log ("RTC Time is not reliable! Power fault? \n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_POST & CONFIG_SYS_POST_RTC */
|
||||
Reference in New Issue
Block a user