This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM5718: Kernel boot hangs

Other Parts Discussed in Thread: AM5718

Hi TI:

Some of our AM5718 main boards can't power up sometimes.

It will block on "start kernel".

MLO I/O re-calibration failed too.

Can you help to analyze root cause?

Thanks

Fail Log:
U-Boot SPL 2017.01-gf8adbe225f (Aug 28 2019 - 00:07:55)
DRA722-GP ES2.0
IODELAY: Isolation of Device IOs failed

Trying to boot from MMC2

U-Boot 2017.01-gf8adbe225f (Aug 28 2019 - 00:07:55 +0000)

CPU  : DRA722-GP ES2.0
Model: TI AM572x EVM Rev A3
Board: RV700
DRAM:  2 GiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1, OMAP SD/MMC: 2

Writing to MMC(1)... done
Writing to redundant MMC(1)... done

Hit any key to stop autoboot:  0
MMC: no card present
switch to partitions #0, OK
mmc1(part 0) is current device
active partition:
1
==>Load Kernel
391736 bytes read in 43 ms (8.7 MiB/s)
SD/MMC found on device 1
** File not found boot.scr **
** File not found uEnv.txt **
3973576 bytes read in 109 ms (34.8 MiB/s)
101626 bytes read in 14 ms (6.9 MiB/s)
## Flattened Device Tree blob at 88000000
   Booting using the fdt blob at 0x88000000
   Loading Device Tree to 8ffe4000, end 8ffffcf9 ... OK

Starting kernel ...

DarkHou

  • Hi Dark,

    dark hou said:
    Some of our AM5718 main boards can't power up sometimes.

    How many AM5718 custom board you have? And how many of these AM5718 custom boards boot fines every time?

    This might be HW malfunction of your custom boards. I would advice to check again your design. You can start with running below diagnostic tests.

    http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_board.html#diagnostics

    You can also check if your DDR memory is setup correctly, please refer to below e2e thread:

    https://e2e.ti.com/support/processors/f/791/t/839672

    dark hou said:
    MLO I/O re-calibration failed too.

    dark hou said:
    IODELAY: Isolation of Device IOs failed

    Refer to below e2e threads which discuss this issue:

    https://e2e.ti.com/support/processors/f/791/t/741632

    https://e2e.ti.com/support/processors/f/791/t/603369

    dark hou said:
    It will block on "start kernel".



    dark hou said:
    Starting kernel ...

    http://processors.wiki.ti.com/index.php/Kernel_-_Common_Problems_Booting_Linux

    https://e2e.ti.com/support/legacy_forums/embedded/linux/f/354/t/347095

    https://e2e.ti.com/support/processors/f/791/t/677706

    https://e2e.ti.com/support/processors/f/791/t/825011

    https://e2e.ti.com/support/processors/f/791/t/789494

    Regards,
    Pavel

  • Hi Pavel:

    Our DDR is 2GB.

    We run mem test in uboot for these main boards.

    The mem test are all pass.

    We have 203 AM5718 main boards. Only 43 main boards have problem.

    Do you have any idea?

    Memory test result in uboot: all pass.

    test ram begin
    test ram 0 times, available mem_size:0x80000000
    test ram 1 times, available mem_size:0x80000000
    test ram 2 times, available mem_size:0x80000000
    test ram 3 times, available mem_size:0x80000000
    test ram 4 times, available mem_size:0x80000000
    test ram 5 times, available mem_size:0x80000000
    test ram 6 times, available mem_size:0x80000000
    test ram 7 times, available mem_size:0x80000000
    test ram 8 times, available mem_size:0x80000000
    test ram 9 times, available mem_size:0x80000000
    test ram 10 times, available mem_size:0x80000000
    test ram 11 times, available mem_size:0x80000000
    test ram 12 times, available mem_size:0x80000000
    test ram 13 times, available mem_size:0x80000000
    test ram 14 times, available mem_size:0x80000000
    test ram 15 times, available mem_size:0x80000000
    test ram 16 times, available mem_size:0x80000000
    test ram 17 times, available mem_size:0x80000000
    test ram 18 times, available mem_size:0x80000000
    test ram 19 times, available mem_size:0x80000000
    test ram 20 times, available mem_size:0x80000000
    test ram 21 times, available mem_size:0x80000000
    test ram 22 times, available mem_size:0x80000000
    test ram 23 times, available mem_size:0x80000000
    test ram 24 times, available mem_size:0x80000000
    test ram 25 times, available mem_size:0x80000000
    test ram 26 times, available mem_size:0x80000000
    test ram 27 times, available mem_size:0x80000000
    test ram 28 times, available mem_size:0x80000000
    test ram 29 times, available mem_size:0x80000000
    test ram 30 times, available mem_size:0x80000000
    test ram 31 times, available mem_size:0x80000000
    test ram 32 times, available mem_size:0x80000000
    test ram 33 times, available mem_size:0x80000000
    test ram 34 times, available mem_size:0x80000000
    test ram 35 times, available mem_size:0x80000000
    test ram 36 times, available mem_size:0x80000000
    test ram 37 times, available mem_size:0x80000000
    test ram 38 times, available mem_size:0x80000000
    test ram 39 times, available mem_size:0x80000000
    test ram 40 times, available mem_size:0x80000000
    test ram 41 times, available mem_size:0x80000000
    test ram 42 times, available mem_size:0x80000000
    test ram 43 times, available mem_size:0x80000000
    test ram 44 times, available mem_size:0x80000000
    test ram 45 times, available mem_size:0x80000000
    test ram 46 times, available mem_size:0x80000000
    test ram 47 times, available mem_size:0x80000000
    test ram 48 times, available mem_size:0x80000000
    test ram 49 times, available mem_size:0x80000000
    test ram 50 times, available mem_size:0x80000000
    test ram 51 times, available mem_size:0x80000000
    test ram 52 times, available mem_size:0x80000000
    test ram 53 times, available mem_size:0x80000000
    test ram 54 times, available mem_size:0x80000000
    test ram 55 times, available mem_size:0x80000000
    test ram 56 times, available mem_size:0x80000000
    test ram 57 times, available mem_size:0x80000000
    test ram 58 times, available mem_size:0x80000000
    test ram 59 times, available mem_size:0x80000000
    test ram 60 times, available mem_size:0x80000000
    test ram 61 times, available mem_size:0x80000000
    test ram 62 times, available mem_size:0x80000000
    test ram 63 times, available mem_size:0x80000000
    test ram 64 times, available mem_size:0x80000000
    test ram 65 times, available mem_size:0x80000000
    test ram 66 times, available mem_size:0x80000000
    test ram 67 times, available mem_size:0x80000000
    test ram 68 times, available mem_size:0x80000000
    test ram 69 times, available mem_size:0x80000000
    test ram 70 times, available mem_size:0x80000000
    test ram 71 times, available mem_size:0x80000000
    test ram 72 times, available mem_size:0x80000000
    test ram 73 times, available mem_size:0x80000000
    test ram 74 times, available mem_size:0x80000000
    test ram 75 times, available mem_size:0x80000000
    test ram 76 times, available mem_size:0x80000000
    test ram 77 times, available mem_size:0x80000000
    test ram 78 times, available mem_size:0x80000000
    test ram 79 times, available mem_size:0x80000000
    test ram 80 times, available mem_size:0x80000000
    test ram 81 times, available mem_size:0x80000000
    test ram 82 times, available mem_size:0x80000000
    test ram 83 times, available mem_size:0x80000000
    test ram 84 times, available mem_size:0x80000000
    test ram 85 times, available mem_size:0x80000000
    test ram 86 times, available mem_size:0x80000000
    test ram 87 times, available mem_size:0x80000000
    test ram 88 times, available mem_size:0x80000000
    test ram 89 times, available mem_size:0x80000000
    test ram 90 times, available mem_size:0x80000000
    test ram 91 times, available mem_size:0x80000000
    test ram 92 times, available mem_size:0x80000000
    test ram 93 times, available mem_size:0x80000000
    test ram 94 times, available mem_size:0x80000000
    test ram 95 times, available mem_size:0x80000000
    test ram 96 times, available mem_size:0x80000000
    test ram 97 times, available mem_size:0x80000000
    test ram 98 times, available mem_size:0x80000000
    test ram 99 times, available mem_size:0x80000000
    Hit any key to stop autoboot:  0
    MMC: no card present
    switch to partitions #0, OK
    mmc1(part 0) is current device
    active partition:

    DarkHou

  • Dark,

    I would suggest you to run the Linux memtester:

    http://www.ti.com/lit/an/spraca1/spraca1.pdf


    You might also run the other diagnostic tests to check if these will pass or fail.

    There might be also some voltage/power HW issue. Please go through below docs also:

    http://www.ti.com/lit/an/sprack7b/sprack7b.pdf

    http://www.ti.com/lit/an/sprack1/sprack1.pdf

    Regards,
    Pavel

  • Hi Pavel:

    DarkHou

  • Hi Pavel:

    Please ignore this reply above.

    We found this issue still exists.

    DarkHou

  • Hi Pavel:

    We found a solution for this issue.

    When I/O re-calibration failed, just need to reboot uboot again.

    The second I/O calibration can work for bad main boards.

    Can you help to review this SW solution below?

    ~/u-boot/board/ti/am57xx/board.c

    void recalibrate_iodelay(void)
    {

       ...

        // Setup I/O isolation
        ret = __recalibrate_iodelay_start();
        if (ret) {
            if (*reboot_reason != REBOOT_BY_IO_CAL_ERROR) {
                *reboot_reason = REBOOT_BY_IO_CAL_ERROR;
            }
            else
            {
                *reboot_reason = NORMAL_POWER_ON;
            }
        }
        else
        {
            *reboot_reason = NORMAL_POWER_ON;
        }

    }

    ~/u-boot/common/autoboot.c

      int *reboot_reason = (int *) OCMC_RAM1_REBOOT_REASON_ADDR;
            
        if (*reboot_reason == REBOOT_BY_IO_CAL_ERROR) {
            do_reset(NULL, 0, 0, NULL);
      }
           

    /*
     * (C) Copyright 2000
     * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    
    #include <common.h>
    #include <autoboot.h>
    #include <bootretry.h>
    #include <cli.h>
    #include <console.h>
    #include <fdtdec.h>
    #include <menu.h>
    #include <post.h>
    #include <u-boot/sha256.h>
    
    DECLARE_GLOBAL_DATA_PTR;
    
    #define MAX_DELAY_STOP_STR 32
    
    #define OCMC_RAM1_REBOOT_REASON_ADDR    0x4035FF00
    #define REBOOT_BY_IO_CAL_ERROR          0x34567801
    
    #ifndef DEBUG_BOOTKEYS
    #define DEBUG_BOOTKEYS 0
    #endif
    #define debug_bootkeys(fmt, args...)		\
    	debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
    
    /* Stored value of bootdelay, used by autoboot_command() */
    static int stored_bootdelay;
    
    #if defined(CONFIG_AUTOBOOT_KEYED)
    #if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
    
    /*
     * Use a "constant-length" time compare function for this
     * hash compare:
     *
     * https://crackstation.net/hashing-security.htm
     */
    static int slow_equals(u8 *a, u8 *b, int len)
    {
    	int diff = 0;
    	int i;
    
    	for (i = 0; i < len; i++)
    		diff |= a[i] ^ b[i];
    
    	return diff == 0;
    }
    
    static int passwd_abort(uint64_t etime)
    {
    	const char *sha_env_str = getenv("bootstopkeysha256");
    	u8 sha_env[SHA256_SUM_LEN];
    	u8 sha[SHA256_SUM_LEN];
    	char presskey[MAX_DELAY_STOP_STR];
    	const char *algo_name = "sha256";
    	u_int presskey_len = 0;
    	int abort = 0;
    	int size;
    	int ret;
    
    	if (sha_env_str == NULL)
    		sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256;
    
    	/*
    	 * Generate the binary value from the environment hash value
    	 * so that we can compare this value with the computed hash
    	 * from the user input
    	 */
    	ret = hash_parse_string(algo_name, sha_env_str, sha_env);
    	if (ret) {
    		printf("Hash %s not supported!\n", algo_name);
    		return 0;
    	}
    
    	/*
    	 * We don't know how long the stop-string is, so we need to
    	 * generate the sha256 hash upon each input character and
    	 * compare the value with the one saved in the environment
    	 */
    	do {
    		if (tstc()) {
    			/* Check for input string overflow */
    			if (presskey_len >= MAX_DELAY_STOP_STR)
    				return 0;
    
    			presskey[presskey_len++] = getc();
    
    			/* Calculate sha256 upon each new char */
    			hash_block(algo_name, (const void *)presskey,
    				   presskey_len, sha, &size);
    
    			/* And check if sha matches saved value in env */
    			if (slow_equals(sha, sha_env, SHA256_SUM_LEN))
    				abort = 1;
    		}
    	} while (!abort && get_ticks() <= etime);
    
    	return abort;
    }
    #else
    static int passwd_abort(uint64_t etime)
    {
    	int abort = 0;
    	struct {
    		char *str;
    		u_int len;
    		int retry;
    	}
    	delaykey[] = {
    		{ .str = getenv("bootdelaykey"),  .retry = 1 },
    		{ .str = getenv("bootstopkey"),   .retry = 0 },
    	};
    
    	char presskey[MAX_DELAY_STOP_STR];
    	u_int presskey_len = 0;
    	u_int presskey_max = 0;
    	u_int i;
    
    #  ifdef CONFIG_AUTOBOOT_DELAY_STR
    	if (delaykey[0].str == NULL)
    		delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
    #  endif
    #  ifdef CONFIG_AUTOBOOT_STOP_STR
    	if (delaykey[1].str == NULL)
    		delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
    #  endif
    
    	for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
    		delaykey[i].len = delaykey[i].str == NULL ?
    				    0 : strlen(delaykey[i].str);
    		delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
    				    MAX_DELAY_STOP_STR : delaykey[i].len;
    
    		presskey_max = presskey_max > delaykey[i].len ?
    				    presskey_max : delaykey[i].len;
    
    		debug_bootkeys("%s key:<%s>\n",
    			       delaykey[i].retry ? "delay" : "stop",
    			       delaykey[i].str ? delaykey[i].str : "NULL");
    	}
    
    	/* In order to keep up with incoming data, check timeout only
    	 * when catch up.
    	 */
    	do {
    		if (tstc()) {
    			if (presskey_len < presskey_max) {
    				presskey[presskey_len++] = getc();
    			} else {
    				for (i = 0; i < presskey_max - 1; i++)
    					presskey[i] = presskey[i + 1];
    
    				presskey[i] = getc();
    			}
    		}
    
    		for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
    			if (delaykey[i].len > 0 &&
    			    presskey_len >= delaykey[i].len &&
    				memcmp(presskey + presskey_len -
    					delaykey[i].len, delaykey[i].str,
    					delaykey[i].len) == 0) {
    					debug_bootkeys("got %skey\n",
    						delaykey[i].retry ? "delay" :
    						"stop");
    
    				/* don't retry auto boot */
    				if (!delaykey[i].retry)
    					bootretry_dont_retry();
    				abort = 1;
    			}
    		}
    	} while (!abort && get_ticks() <= etime);
    
    	return abort;
    }
    #endif
    
    /***************************************************************************
     * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
     * returns: 0 -  no key string, allow autoboot 1 - got key string, abort
     */
    static int __abortboot(int bootdelay)
    {
    	int abort;
    	uint64_t etime = endtick(bootdelay);
    
    #  ifdef CONFIG_AUTOBOOT_PROMPT
    	/*
    	 * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards.
    	 * To print the bootdelay value upon bootup.
    	 */
    	printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
    #  endif
    
    	abort = passwd_abort(etime);
    	if (!abort)
    		debug_bootkeys("key timeout\n");
    
    	return abort;
    }
    
    # else	/* !defined(CONFIG_AUTOBOOT_KEYED) */
    
    #ifdef CONFIG_MENUKEY
    static int menukey;
    #endif
    
    static int __abortboot(int bootdelay)
    {
    	int abort = 0;
    	unsigned long ts;
    
    #ifdef CONFIG_MENUPROMPT
    	printf(CONFIG_MENUPROMPT);
    #else
    	printf("Hit any key to stop autoboot: %2d ", bootdelay);
    #endif
    
      int *reboot_reason = (int *) OCMC_RAM1_REBOOT_REASON_ADDR;
    		
    	if (*reboot_reason == REBOOT_BY_IO_CAL_ERROR) {
    	    do_reset(NULL, 0, 0, NULL);
      }
    		
    	/*
    	 * Check if key already pressed
    	 */
    	if (tstc()) {	/* we got a key press	*/
    		(void) getc();  /* consume input	*/
    		puts("\b\b\b 0");
    		abort = 1;	/* don't auto boot	*/
    	}
    
    	while ((bootdelay > 0) && (!abort)) {
    		--bootdelay;
    		/* delay 1000 ms */
    		ts = get_timer(0);
    		do {
    			if (tstc()) {	/* we got a key press	*/
    				abort  = 1;	/* don't auto boot	*/
    				bootdelay = 0;	/* no more delay	*/
    # ifdef CONFIG_MENUKEY
    				menukey = getc();
    # else
    				(void) getc();  /* consume input	*/
    # endif
    				break;
    			}
    			udelay(10000);
    		} while (!abort && get_timer(ts) < 1000);
    
    		printf("\b\b\b%2d ", bootdelay);
    	}
    
    	putc('\n');
    
    	return abort;
    }
    # endif	/* CONFIG_AUTOBOOT_KEYED */
    
    static int abortboot(int bootdelay)
    {
    	int abort = 0;
    
    	if (bootdelay >= 0)
    		abort = __abortboot(bootdelay);
    
    #ifdef CONFIG_SILENT_CONSOLE
    	if (abort)
    		gd->flags &= ~GD_FLG_SILENT;
    #endif
    
    	return abort;
    }
    
    static void process_fdt_options(const void *blob)
    {
    #if defined(CONFIG_OF_CONTROL) && defined(CONFIG_SYS_TEXT_BASE)
    	ulong addr;
    
    	/* Add an env variable to point to a kernel payload, if available */
    	addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
    	if (addr)
    		setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
    
    	/* Add an env variable to point to a root disk, if available */
    	addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
    	if (addr)
    		setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
    #endif /* CONFIG_OF_CONTROL && CONFIG_SYS_TEXT_BASE */
    }
    
    const char *bootdelay_process(void)
    {
    	char *s;
    	int bootdelay;
    #ifdef CONFIG_BOOTCOUNT_LIMIT
    	unsigned long bootcount = 0;
    	unsigned long bootlimit = 0;
    #endif /* CONFIG_BOOTCOUNT_LIMIT */
    
    #ifdef CONFIG_BOOTCOUNT_LIMIT
    	bootcount = bootcount_load();
    	bootcount++;
    	bootcount_store(bootcount);
    	setenv_ulong("bootcount", bootcount);
    	bootlimit = getenv_ulong("bootlimit", 10, 0);
    #endif /* CONFIG_BOOTCOUNT_LIMIT */
    
    	s = getenv("bootdelay");
    	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
    
    #ifdef CONFIG_OF_CONTROL
    	bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
    			bootdelay);
    #endif
    
    	debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
    
    #if defined(CONFIG_MENU_SHOW)
    	bootdelay = menu_show(bootdelay);
    #endif
    	bootretry_init_cmd_timeout();
    
    #ifdef CONFIG_POST
    	if (gd->flags & GD_FLG_POSTFAIL) {
    		s = getenv("failbootcmd");
    	} else
    #endif /* CONFIG_POST */
    #ifdef CONFIG_BOOTCOUNT_LIMIT
    	if (bootlimit && (bootcount > bootlimit)) {
    		printf("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
    		       (unsigned)bootlimit);
    		s = getenv("altbootcmd");
    	} else
    #endif /* CONFIG_BOOTCOUNT_LIMIT */
    		s = getenv("bootcmd");
    
    	process_fdt_options(gd->fdt_blob);
    	stored_bootdelay = bootdelay;
    
    	return s;
    }
    
    void autoboot_command(const char *s)
    {
    	debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
    
    	if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
    #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
    		int prev = disable_ctrlc(1);	/* disable Control C checking */
    #endif
    
    		run_command_list(s, -1, 0);
    
    #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
    		disable_ctrlc(prev);	/* restore Control C checking */
    #endif
    	}
    
    #ifdef CONFIG_MENUKEY
    	if (menukey == CONFIG_MENUKEY) {
    		s = getenv("menucmd");
    		if (s)
    			run_command_list(s, -1, 0);
    	}
    #endif /* CONFIG_MENUKEY */
    }
    

    /*
     * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
     *
     * Author: Felipe Balbi <balbi@ti.com>
     *
     * Based on board/ti/dra7xx/evm.c
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    
    #include <common.h>
    #include <palmas.h>
    #include <sata.h>
    #include <usb.h>
    #include <asm/omap_common.h>
    #include <asm/omap_sec_common.h>
    #include <asm/emif.h>
    #include <asm/gpio.h>
    #include <asm/arch/gpio.h>
    #include <asm/arch/clock.h>
    #include <asm/arch/dra7xx_iodelay.h>
    #include <asm/arch/sys_proto.h>
    #include <asm/arch/mmc_host_def.h>
    #include <asm/arch/sata.h>
    #include <asm/arch/gpio.h>
    #include <asm/arch/omap.h>
    #include <environment.h>
    #include <usb.h>
    #include <linux/usb/gadget.h>
    #include <dwc3-uboot.h>
    #include <dwc3-omap-uboot.h>
    #include <ti-usb-phy-uboot.h>
    
    #include "mux_data.h"
    #include "hw_info.h"
    
    #ifdef CONFIG_DRIVER_TI_CPSW
    #include <cpsw.h>
    #endif
    
    /* The processor supports both DDR-1066 & DDR-1333 and the installed DRAM
     * supports even higher speeds.  This board file was originally developed from
     * one supporting a TI evaluation board and needed to be changed to match the
     * RV700 HW.  The original change was an ugly hack whose effect was to select
     * DDR-1066.  When this code was later reviewed and the unfortunate speed
     * choice was discovered, it was decided that it was too late in the project
     * to risk changing to the higher speed and so the first version will ship
     * with DDR-1066.
     *
     * Note that there's a spec in the data sheet that implies that DDR-1333 isn't
     * supported however this was chased down with TI and that spec was determined
     * to be a typo.  By the time this comment is next read, it's possible that the
     * data sheet will have been updated to correct that error.
     *
     * Bottom line: at some future point when there's sufficient test time
     * available, it is probably worth selecting DDR-1333 for a 25% speed boost.
     */
    #define DRAM_SPEED 1066  /* 1.870 ns cyle time, CL = 7 */
    //#define DRAM_SPEED 1333  /* 1.500 ns cyle time, CL = 9 */
    
    DECLARE_GLOBAL_DATA_PTR;
    
    /* GPIO 7_11 */
    #define GPIO_DDR_VTT_EN 203
    
    #define SYSINFO_BOARD_NAME_MAX_LEN	45
    
    #define TPS65903X_PRIMARY_SECONDARY_PAD2	0xFB
    #define TPS65903X_PAD2_POWERHOLD_MASK		0x20
    
    #define OCMC_RAM1_REBOOT_REASON_ADDR  0x4035FF00
    #define REBOOT_BY_IO_CAL_ERROR        0x34567801
    #define NORMAL_POWER_ON               0x32346643
    
    /* define "board info string": must start with "Board: " and end w/ '\n' */
    const struct omap_sysinfo sysinfo = {
    	"Board: RV700\n"
    };
    
    static const struct dmm_lisa_map_regs rv700_am5718_lisa_regs = {
    	.dmm_lisa_map_3 = 0x80700100,
    	.is_ma_present  = 0x1
    };
    
    void emif_get_dmm_regs(const struct dmm_lisa_map_regs **dmm_lisa_regs)
    {
    	*dmm_lisa_regs = &rv700_am5718_lisa_regs;		
    }
    
    static const struct emif_regs beagle_x15_emif1_ddr3_532mhz_emif_regs = {
    	.sdram_config_init		= 0x61851b32,
    	.sdram_config			= 0x61851b32,
    	.sdram_config2			= 0x08000000,
    	.ref_ctrl			= 0x000040F1,
    	.ref_ctrl_final			= 0x00001035,
    	.sdram_tim1			= 0xcccf36ab,
    	.sdram_tim2			= 0x308f7fda,
    	.sdram_tim3			= 0x409f88a8,
    	.read_idle_ctrl			= 0x00050000,
    	.zq_config			= 0x5007190b,
    	.temp_alert_config		= 0x00000000,
    	.emif_ddr_phy_ctlr_1_init 	= 0x0024400b,
    	.emif_ddr_phy_ctlr_1		= 0x0e24400b,
    	.emif_ddr_ext_phy_ctrl_1 	= 0x10040100,
    	.emif_ddr_ext_phy_ctrl_2 	= 0x00910091,
    	.emif_ddr_ext_phy_ctrl_3 	= 0x00950095,
    	.emif_ddr_ext_phy_ctrl_4 	= 0x009b009b,
    	.emif_ddr_ext_phy_ctrl_5 	= 0x009e009e,
    	.emif_rd_wr_lvl_rmp_win		= 0x00000000,
    	.emif_rd_wr_lvl_rmp_ctl		= 0x80000000,
    	.emif_rd_wr_lvl_ctl		= 0x00000000,
    	.emif_rd_wr_exec_thresh		= 0x00000305
    };
    
    /* Ext phy ctrl regs 1-35 */
    static const u32 beagle_x15_emif1_ddr3_ext_phy_ctrl_const_regs[] = {
    	0x10040100,
    	0x00910091,
    	0x00950095,
    	0x009B009B,
    	0x009E009E,
    	0x00980098,
    	0x00340034,
    	0x00350035,
    	0x00340034,
    	0x00310031,
    	0x00340034,
    	0x007F007F,
    	0x007F007F,
    	0x007F007F,
    	0x007F007F,
    	0x007F007F,
    	0x00480048,
    	0x004A004A,
    	0x00520052,
    	0x00550055,
    	0x00500050,
    	0x00000000,
    	0x00600020,
    	0x40011080,
    	0x08102040,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0
    };
    
    static const struct emif_regs beagle_x15_emif2_ddr3_532mhz_emif_regs = {
    	.sdram_config_init		= 0x61851b32,
    	.sdram_config			= 0x61851b32,
    	.sdram_config2			= 0x08000000,
    	.ref_ctrl			= 0x000040F1,
    	.ref_ctrl_final			= 0x00001035,
    	.sdram_tim1			= 0xcccf36b3,
    	.sdram_tim2			= 0x308f7fda,
    	.sdram_tim3			= 0x407f88a8,
    	.read_idle_ctrl			= 0x00050000,
    	.zq_config			= 0x5007190b,
    	.temp_alert_config		= 0x00000000,
    	.emif_ddr_phy_ctlr_1_init 	= 0x0024400b,
    	.emif_ddr_phy_ctlr_1		= 0x0e24400b,
    	.emif_ddr_ext_phy_ctrl_1 	= 0x10040100,
    	.emif_ddr_ext_phy_ctrl_2 	= 0x00910091,
    	.emif_ddr_ext_phy_ctrl_3 	= 0x00950095,
    	.emif_ddr_ext_phy_ctrl_4 	= 0x009b009b,
    	.emif_ddr_ext_phy_ctrl_5 	= 0x009e009e,
    	.emif_rd_wr_lvl_rmp_win		= 0x00000000,
    	.emif_rd_wr_lvl_rmp_ctl		= 0x80000000,
    	.emif_rd_wr_lvl_ctl		= 0x00000000,
    	.emif_rd_wr_exec_thresh		= 0x00000305
    };
    
    static const u32 beagle_x15_emif2_ddr3_ext_phy_ctrl_const_regs[] = {
    	0x10040100,
    	0x00910091,
    	0x00950095,
    	0x009B009B,
    	0x009E009E,
    	0x00980098,
    	0x00340034,
    	0x00350035,
    	0x00340034,
    	0x00310031,
    	0x00340034,
    	0x007F007F,
    	0x007F007F,
    	0x007F007F,
    	0x007F007F,
    	0x007F007F,
    	0x00480048,
    	0x004A004A,
    	0x00520052,
    	0x00550055,
    	0x00500050,
    	0x00000000,
    	0x00600020,
    	0x40011080,
    	0x08102040,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0,
    	0x0
    };
    
    #if DRAM_SPEED == 1333
    static const struct emif_regs am571x_emif1_ddr3_666mhz_emif_regs = {
    	.sdram_config_init		= 0x61863332,
    	.sdram_config			= 0x61863332,
    	.sdram_config2			= 0x08000000,
    	.ref_ctrl			= 0x0000514d,
    	.ref_ctrl_final			= 0x0000144a,
    	.sdram_tim1			= 0xd333887c,
    	.sdram_tim2			= 0x40b37fe3,
    	.sdram_tim3			= 0x409f8ada,
    	.read_idle_ctrl			= 0x00050000,
    	.zq_config			= 0x5007190b,
    	.temp_alert_config		= 0x00000000,
    	.emif_ddr_phy_ctlr_1_init	= 0x0024400f,
    	.emif_ddr_phy_ctlr_1		= 0x0e24400f,
    	.emif_ddr_ext_phy_ctrl_1	= 0x10040100,
    	.emif_ddr_ext_phy_ctrl_2	= 0x00910091,
    	.emif_ddr_ext_phy_ctrl_3	= 0x00950095,
    	.emif_ddr_ext_phy_ctrl_4	= 0x009b009b,
    	.emif_ddr_ext_phy_ctrl_5	= 0x009e009e,
    	.emif_rd_wr_lvl_rmp_win		= 0x00000000,
    	.emif_rd_wr_lvl_rmp_ctl		= 0x80000000,
    	.emif_rd_wr_lvl_ctl		= 0x00000000,
    	.emif_rd_wr_exec_thresh		= 0x00000305
    };
    #endif
    
    void emif_get_reg_dump(u32 emif_nr, const struct emif_regs **regs)
    {
    	switch (emif_nr) {
    	case 1:
    #if DRAM_SPEED == 1066
    		*regs = &beagle_x15_emif1_ddr3_532mhz_emif_regs;
    #elif DRAM_SPEED == 1333
    		*regs = &am571x_emif1_ddr3_666mhz_emif_regs;
    #else
        #error DRAM_SPEED not defined
    #endif
    		break;
    	case 2:
    		*regs = &beagle_x15_emif2_ddr3_532mhz_emif_regs;
    		break;
    	}
    }
    
    void emif_get_ext_phy_ctrl_const_regs(u32 emif_nr, const u32 **regs, u32 *size)
    {
    	switch (emif_nr) {
    	case 1:
    		*regs = beagle_x15_emif1_ddr3_ext_phy_ctrl_const_regs;
    		*size = ARRAY_SIZE(beagle_x15_emif1_ddr3_ext_phy_ctrl_const_regs);
    		break;
    	case 2:
    		*regs = beagle_x15_emif2_ddr3_ext_phy_ctrl_const_regs;
    		*size = ARRAY_SIZE(beagle_x15_emif2_ddr3_ext_phy_ctrl_const_regs);
    		break;
    	}
    }
    
    struct vcores_data rv700_volts = {
    	.mpu.value[OPP_NOM]	= VDD_MPU_DRA7_NOM,
    	.mpu.efuse.reg[OPP_NOM]	= STD_FUSE_OPP_VMIN_MPU_NOM,
    	.mpu.efuse.reg_bits     = DRA752_EFUSE_REGBITS,
    	.mpu.addr		= TPS659038_REG_ADDR_SMPS12,
    	.mpu.pmic		= &tps659038,
    	.mpu.abb_tx_done_mask	= OMAP_ABB_MPU_TXDONE_MASK,
    
    	.eve.value[OPP_NOM]	= VDD_EVE_DRA7_NOM,
    	.eve.value[OPP_OD]	= VDD_EVE_DRA7_OD,
    	.eve.value[OPP_HIGH]	= VDD_EVE_DRA7_HIGH,
    	.eve.efuse.reg[OPP_NOM]	= STD_FUSE_OPP_VMIN_DSPEVE_NOM,
    	.eve.efuse.reg[OPP_OD]	= STD_FUSE_OPP_VMIN_DSPEVE_OD,
    	.eve.efuse.reg[OPP_HIGH]	= STD_FUSE_OPP_VMIN_DSPEVE_HIGH,
    	.eve.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
    	.eve.addr		= TPS659038_REG_ADDR_SMPS45,
    	.eve.pmic		= &tps659038,
    	.eve.abb_tx_done_mask	= OMAP_ABB_EVE_TXDONE_MASK,
    
    	.gpu.value[OPP_NOM]	= VDD_GPU_DRA7_NOM,
    	.gpu.value[OPP_OD]	= VDD_GPU_DRA7_OD,
    	.gpu.value[OPP_HIGH]	= VDD_GPU_DRA7_HIGH,
    	.gpu.efuse.reg[OPP_NOM]	= STD_FUSE_OPP_VMIN_GPU_NOM,
    	.gpu.efuse.reg[OPP_OD]	= STD_FUSE_OPP_VMIN_GPU_OD,
    	.gpu.efuse.reg[OPP_HIGH]	= STD_FUSE_OPP_VMIN_GPU_HIGH,
    	.gpu.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
    	.gpu.addr		= TPS659038_REG_ADDR_SMPS45,
    	.gpu.pmic		= &tps659038,
    	.gpu.abb_tx_done_mask	= OMAP_ABB_GPU_TXDONE_MASK,
    
    	.core.value[OPP_NOM]	= VDD_CORE_DRA7_NOM,
    	.core.efuse.reg[OPP_NOM]	= STD_FUSE_OPP_VMIN_CORE_NOM,
    	.core.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
    	.core.addr		= TPS659038_REG_ADDR_SMPS6,
    	.core.pmic		= &tps659038,
    
    	.iva.value[OPP_NOM]	= VDD_IVA_DRA7_NOM,
    	.iva.value[OPP_OD]	= VDD_IVA_DRA7_OD,
    	.iva.value[OPP_HIGH]	= VDD_IVA_DRA7_HIGH,
    	.iva.efuse.reg[OPP_NOM]	= STD_FUSE_OPP_VMIN_IVA_NOM,
    	.iva.efuse.reg[OPP_OD]	= STD_FUSE_OPP_VMIN_IVA_OD,
    	.iva.efuse.reg[OPP_HIGH]	= STD_FUSE_OPP_VMIN_IVA_HIGH,
    	.iva.efuse.reg_bits	= DRA752_EFUSE_REGBITS,
    	.iva.addr		= TPS659038_REG_ADDR_SMPS45,
    	.iva.pmic		= &tps659038,
    	.iva.abb_tx_done_mask	= OMAP_ABB_IVA_TXDONE_MASK,
    };
    
    int get_voltrail_opp(int rail_offset)
    {
    	int opp;
    
    	switch (rail_offset) {
    	case VOLT_MPU:
    		opp = DRA7_MPU_OPP;
    		break;
    	case VOLT_CORE:
    		opp = DRA7_CORE_OPP;
    		break;
    	case VOLT_GPU:
    		opp = DRA7_GPU_OPP;
    		break;
    	case VOLT_EVE:
    		opp = DRA7_DSPEVE_OPP;
    		break;
    	case VOLT_IVA:
    		opp = DRA7_IVA_OPP;
    		break;
    	default:
    		opp = OPP_NOM;
    	}
    
    	return opp;
    }
    
    void vcores_init(void)
    {
    	*omap_vcores = &rv700_volts;
    }
    
    void hw_data_init(void)
    {
    	*prcm = &dra7xx_prcm;
    #if DRAM_SPEED == 1066
    	*dplls_data = &dra7xx_dplls;
    #elif DRAM_SPEED == 1333
    	*dplls_data = &dra72x_dplls;
    #else
        #error DRAM_SPEED not defined
    #endif
    	*ctrl = &dra7xx_ctrl;
    }
    
    int board_init(void)
    {
    	gpmc_init();
    	gd->bd->bi_boot_params = (CONFIG_SYS_SDRAM_BASE + 0x100);
    
    	return 0;
    }
    
    int board_late_init(void)
    {
    	/*
    	 * DEV_CTRL.DEV_ON = 1 please - else palmas switches off in 8 seconds
    	 * This is the POWERHOLD-in-Low behavior.
    	 */
    	palmas_i2c_write_u8(TPS65903X_CHIP_P1, 0xA0, 0x1);
    
    	/*
    	 * Set the GPIO7 Pad to POWERHOLD. This has higher priority
    	 * over DEV_CTRL.DEV_ON bit. This can be reset in case of
    	 * PMIC Power off. So to be on the safer side set it back
    	 * to POWERHOLD mode irrespective of the current state.
    	 */
    	u8 val;
    	palmas_i2c_read_u8(TPS65903X_CHIP_P1, TPS65903X_PRIMARY_SECONDARY_PAD2,
    			   &val);
    	val = val | TPS65903X_PAD2_POWERHOLD_MASK;
    	palmas_i2c_write_u8(TPS65903X_CHIP_P1, TPS65903X_PRIMARY_SECONDARY_PAD2,
    			    val);
    
    #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_DRIVER_TI_CPSW)
    	board_ti_set_ethaddr(2);
    #endif
    
    	if (get_hw_version() > 0) {
    		const struct pad_conf_entry *pconf_hw_1_0;
    		int pconf_sz_hw_1_0;
    	
    		pconf_hw_1_0 = core_padconf_array_rv700_am5718_board_1_0;
    		pconf_sz_hw_1_0 =
    			ARRAY_SIZE(core_padconf_array_rv700_am5718_board_1_0);
    		do_set_mux32((*ctrl)->control_padconf_core_base,
    			     pconf_hw_1_0, pconf_sz_hw_1_0);
    	}
    	
    	return 0;
    }
    
    void set_muxconf_regs(void)
    {
    	do_set_mux32((*ctrl)->control_padconf_core_base,
    		     early_padconf, ARRAY_SIZE(early_padconf));
    }
    
    #ifdef CONFIG_IODELAY_RECALIBRATION
    void recalibrate_iodelay(void)
    {
    	const struct pad_conf_entry *pconf;
    	const struct iodelay_cfg_entry *iod;
    	int pconf_sz, iod_sz;
    	int ret;
    	int *reboot_reason = (int *) OCMC_RAM1_REBOOT_REASON_ADDR;
    
    	pconf = core_padconf_array_rv700_am5718_board_base;
    	pconf_sz = ARRAY_SIZE(core_padconf_array_rv700_am5718_board_base);
    
    	iod = iodelay_cfg_array_rv700_am5718_board_base;
    	iod_sz = ARRAY_SIZE(iodelay_cfg_array_rv700_am5718_board_base);
    	
    	// Setup I/O isolation 
    	ret = __recalibrate_iodelay_start();
    	if (ret) {
    		if (*reboot_reason != REBOOT_BY_IO_CAL_ERROR) {
    			*reboot_reason = REBOOT_BY_IO_CAL_ERROR;
    		}
    		else
    		{
    			*reboot_reason = NORMAL_POWER_ON;
    		}
    	}
    	else
    	{
    		*reboot_reason = NORMAL_POWER_ON;
    	}
    
    	/* Do the muxing here */
    	do_set_mux32((*ctrl)->control_padconf_core_base, pconf, pconf_sz);
    
    	/* Setup IOdelay configuration */
    	ret = do_set_iodelay((*ctrl)->iodelay_config_base, iod, iod_sz);
    
    	/* Closeup.. remove isolation */
    	__recalibrate_iodelay_end(ret);
    }
    #endif
    
    #if defined(CONFIG_GENERIC_MMC)
    int board_mmc_init(bd_t *bis)
    {
    	omap_mmc_init(0, 0, 0, -1, -1);
    	omap_mmc_init(1, 0, 0, -1, -1);
    	return 0;
    }
    #endif
    
    #if defined(CONFIG_IODELAY_RECALIBRATION) && \
    	(defined(CONFIG_SPL_BUILD) || !defined(CONFIG_DM_MMC))
    
    struct pinctrl_desc {
    	const char *name;
    	struct omap_hsmmc_pinctrl_state *pinctrl;
    };
    
    static struct pinctrl_desc pinctrl_descs_hsmmc1[] = {
    	{"default", &hsmmc1_default},
    	{"hs", &hsmmc1_default},
    	{NULL}
    };
    
    static struct pinctrl_desc pinctrl_descs_hsmmc2_am571[] = {
    	{"default", &hsmmc2_default_hs},
    	{"hs", &hsmmc2_default_hs},
    	{"ddr_1_8v", &hsmmc2_ddr_am571},
    	{NULL}
    };
    
    struct omap_hsmmc_pinctrl_state *platform_fixup_get_pinctrl_by_mode
    				  (struct hsmmc *base, const char *mode)
    {
    	struct pinctrl_desc *p = NULL;
    
    	switch ((u32)&base->res1) {
    	case OMAP_HSMMC1_BASE:
    		p = pinctrl_descs_hsmmc1;
    		break;
    	case OMAP_HSMMC2_BASE:
    		p = pinctrl_descs_hsmmc2_am571;
    	default:
    		break;
    	}
    
    	if (!p) {
    		printf("%s no pinctrl defined for MMC@%p\n", __func__,
    		       base);
    		return NULL;
    	}
    	while (p->name) {
    		if (strcmp(mode, p->name) == 0)
    			return p->pinctrl;
    		p++;
    	}
    	return NULL;
    }
    #endif
    
    #ifdef CONFIG_OMAP_HSMMC
    int platform_fixup_disable_uhs_mode(void)
    {
    	return omap_revision() == DRA752_ES1_1;
    }
    #endif
    
    #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_OS_BOOT)
    int spl_start_uboot(void)
    {
    	/* break into full u-boot on 'c' */
    	if (serial_tstc() && serial_getc() == 'c')
    		return 1;
    
    #ifdef CONFIG_SPL_ENV_SUPPORT
    	env_init();
    	env_relocate_spec();
    	if (getenv_yesno("boot_os") != 1)
    		return 1;
    #endif
    
    	return 0;
    }
    #endif
    
    #ifdef CONFIG_USB_DWC3
    static struct dwc3_device usb_otg_ss2 = {
    	.maximum_speed = USB_SPEED_HIGH,
    	.base = DRA7_USB_OTG_SS2_BASE,
    	.tx_fifo_resize = false,
    	.index = 1,
    };
    
    static struct dwc3_omap_device usb_otg_ss2_glue = {
    	.base = (void *)DRA7_USB_OTG_SS2_GLUE_BASE,
    	.utmi_mode = DWC3_OMAP_UTMI_MODE_SW,
    	.index = 1,
    };
    
    static struct ti_usb_phy_device usb_phy2_device = {
    	.usb2_phy_power = (void *)DRA7_USB2_PHY2_POWER,
    	.index = 1,
    };
    
    int usb_gadget_handle_interrupts(int index)
    {
    	u32 status;
    
    	status = dwc3_omap_uboot_interrupt_status(index);
    	if (status)
    		dwc3_uboot_handle_interrupt(index);
    
    	return 0;
    }
    #endif /* CONFIG_USB_DWC3 */
    
    #if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP)
    int board_usb_init(int index, enum usb_init_type init)
    {
    	enable_usb_clocks(index);
    	switch (index) {
    	case 0:
    		if (init == USB_INIT_DEVICE) {
    			printf("port %d can't be used as device\n", index);
    			disable_usb_clocks(index);
    			return -EINVAL;
    		}
    		break;
    	case 1:
    		if (init == USB_INIT_DEVICE) {
    #ifdef CONFIG_USB_DWC3
    			usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL;
    			usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
    			ti_usb_phy_uboot_init(&usb_phy2_device);
    			dwc3_omap_uboot_init(&usb_otg_ss2_glue);
    			dwc3_uboot_init(&usb_otg_ss2);
    #endif
    		} else {
    			printf("port %d can't be used as host\n", index);
    			disable_usb_clocks(index);
    			return -EINVAL;
    		}
    
    		break;
    	default:
    		printf("Invalid Controller Index\n");
    	}
    
    	return 0;
    }
    
    int board_usb_cleanup(int index, enum usb_init_type init)
    {
    #ifdef CONFIG_USB_DWC3
    	switch (index) {
    	case 0:
    	case 1:
    		if (init == USB_INIT_DEVICE) {
    			ti_usb_phy_uboot_exit(index);
    			dwc3_uboot_exit(index);
    			dwc3_omap_uboot_exit(index);
    		}
    		break;
    	default:
    		printf("Invalid Controller Index\n");
    	}
    #endif
    	disable_usb_clocks(index);
    	return 0;
    }
    #endif /* defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) */
    
    #ifdef CONFIG_DRIVER_TI_CPSW
    
    /* Delay value to add to calibrated value */
    #define RGMII0_TXCTL_DLY_VAL		((0x3 << 5) + 0x8)
    #define RGMII0_TXD0_DLY_VAL		((0x3 << 5) + 0x8)
    #define RGMII0_TXD1_DLY_VAL		((0x3 << 5) + 0x2)
    #define RGMII0_TXD2_DLY_VAL		((0x4 << 5) + 0x0)
    #define RGMII0_TXD3_DLY_VAL		((0x4 << 5) + 0x0)
    #define VIN2A_D13_DLY_VAL		((0x3 << 5) + 0x8)
    #define VIN2A_D17_DLY_VAL		((0x3 << 5) + 0x8)
    #define VIN2A_D16_DLY_VAL		((0x3 << 5) + 0x2)
    #define VIN2A_D15_DLY_VAL		((0x4 << 5) + 0x0)
    #define VIN2A_D14_DLY_VAL		((0x4 << 5) + 0x0)
    
    static void cpsw_control(int enabled)
    {
    	/* VTP can be added here */
    }
    
    static struct cpsw_slave_data cpsw_slaves[] = {
    	{
    		.slave_reg_ofs	= 0x208,
    		.sliver_reg_ofs	= 0xd80,
    		.phy_addr	= 1,
    	},
    	{
    		.slave_reg_ofs	= 0x308,
    		.sliver_reg_ofs	= 0xdc0,
    		.phy_addr	= 2,
    	},
    };
    
    static struct cpsw_platform_data cpsw_data = {
    	.mdio_base		= CPSW_MDIO_BASE,
    	.cpsw_base		= CPSW_BASE,
    	.mdio_div		= 0xff,
    	.channels		= 8,
    	.cpdma_reg_ofs		= 0x800,
    	.slaves			= 1,
    	.slave_data		= cpsw_slaves,
    	.ale_reg_ofs		= 0xd00,
    	.ale_entries		= 1024,
    	.host_port_reg_ofs	= 0x108,
    	.hw_stats_reg_ofs	= 0x900,
    	.bd_ram_ofs		= 0x2000,
    	.mac_control		= (1 << 5),
    	.control		= cpsw_control,
    	.host_port_num		= 0,
    	.version		= CPSW_CTRL_VERSION_2,
    };
    
    static u64 mac_to_u64(u8 mac[6])
    {
    	int i;
    	u64 addr = 0;
    
    	for (i = 0; i < 6; i++) {
    		addr <<= 8;
    		addr |= mac[i];
    	}
    
    	return addr;
    }
    
    static void u64_to_mac(u64 addr, u8 mac[6])
    {
    	mac[5] = addr;
    	mac[4] = addr >> 8;
    	mac[3] = addr >> 16;
    	mac[2] = addr >> 24;
    	mac[1] = addr >> 32;
    	mac[0] = addr >> 40;
    }
    
    int board_eth_init(bd_t *bis)
    {
    	int ret;
    	uint8_t mac_addr[6];
    	uint32_t mac_hi, mac_lo;
    	uint32_t ctrl_val;
    	int i;
    	u64 mac1, mac2;
    	u8 mac_addr1[6], mac_addr2[6];
    	int num_macs;
    
    	/* try reading mac address from efuse */
    	mac_lo = readl((*ctrl)->control_core_mac_id_0_lo);
    	mac_hi = readl((*ctrl)->control_core_mac_id_0_hi);
    	mac_addr[0] = (mac_hi & 0xFF0000) >> 16;
    	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
    	mac_addr[2] = mac_hi & 0xFF;
    	mac_addr[3] = (mac_lo & 0xFF0000) >> 16;
    	mac_addr[4] = (mac_lo & 0xFF00) >> 8;
    	mac_addr[5] = mac_lo & 0xFF;
    
    	if (!getenv("ethaddr")) {
    		printf("<ethaddr> not set. Validating first E-fuse MAC\n");
    
    		if (is_valid_ethaddr(mac_addr))
    			eth_setenv_enetaddr("ethaddr", mac_addr);
    	}
    
    	mac_lo = readl((*ctrl)->control_core_mac_id_1_lo);
    	mac_hi = readl((*ctrl)->control_core_mac_id_1_hi);
    	mac_addr[0] = (mac_hi & 0xFF0000) >> 16;
    	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
    	mac_addr[2] = mac_hi & 0xFF;
    	mac_addr[3] = (mac_lo & 0xFF0000) >> 16;
    	mac_addr[4] = (mac_lo & 0xFF00) >> 8;
    	mac_addr[5] = mac_lo & 0xFF;
    
    	if (!getenv("eth1addr")) {
    		if (is_valid_ethaddr(mac_addr))
    			eth_setenv_enetaddr("eth1addr", mac_addr);
    	}
    
    	ctrl_val = readl((*ctrl)->control_core_control_io1) & (~0x33);
    	ctrl_val |= 0x22;
    	writel(ctrl_val, (*ctrl)->control_core_control_io1);
    
    	ret = cpsw_register(&cpsw_data);
    	if (ret < 0)
    		printf("Error %d registering CPSW switch\n", ret);
    
    	/*
    	 * Export any Ethernet MAC addresses from EEPROM.
    	 * On AM57xx the 2 MAC addresses define the address range
    	 */
    	board_ti_get_eth_mac_addr(0, mac_addr1);
    	board_ti_get_eth_mac_addr(1, mac_addr2);
    
    	if (is_valid_ethaddr(mac_addr1) && is_valid_ethaddr(mac_addr2)) {
    		mac1 = mac_to_u64(mac_addr1);
    		mac2 = mac_to_u64(mac_addr2);
    
    		/* must contain an address range */
    		num_macs = mac2 - mac1 + 1;
    		/* <= 50 to protect against user programming error */
    		if (num_macs > 0 && num_macs <= 50) {
    			for (i = 0; i < num_macs; i++) {
    				u64_to_mac(mac1 + i, mac_addr);
    				if (is_valid_ethaddr(mac_addr)) {
    					eth_setenv_enetaddr_by_index("eth",
    								     i + 2,
    								     mac_addr);
    				}
    			}
    		}
    	}
    
    	return ret;
    }
    #endif /* CONFIG_DRIVER_TI_CPSW */
    
    #ifdef CONFIG_BOARD_EARLY_INIT_F
    /* VTT regulator enable */
    static inline void vtt_regulator_enable(void)
    {
    	if (omap_hw_init_context() == OMAP_INIT_CONTEXT_UBOOT_AFTER_SPL)
    		return;
    
    	gpio_request(GPIO_DDR_VTT_EN, "ddr_vtt_en");
    	gpio_direction_output(GPIO_DDR_VTT_EN, 1);
    }
    
    int board_early_init_f(void)
    {
    	vtt_regulator_enable();
    	return 0;
    }
    #endif
    
    #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
    int ft_board_setup(void *blob, bd_t *bd)
    {
    	ft_cpu_setup(blob, bd);
    
    	return 0;
    }
    #endif
    
    #ifdef CONFIG_TI_SECURE_DEVICE
    void board_fit_image_post_process(void **p_image, size_t *p_size)
    {
    	secure_boot_verify_image(p_image, p_size);
    }
    
    void board_tee_image_process(ulong tee_image, size_t tee_size)
    {
    	secure_tee_install((u32)tee_image);
    }
    
    U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_TEE, board_tee_image_process);
    #endif
    

    DarkHou

  • DarkHou,

    Using u-boot do_reset() function to reset the AM57x device at u-boot stage, is the correct approach.

    Regards,
    Pavel

  • Hi Pavel:

    Thanks for your reply.

    We just want to double confirm it.

    For I/O re-calibration failed issue, can we use do_reset function to cover it?

    Is any risks for this solution?

    Thanks

    DarkHou

  • dark hou said:
    For I/O re-calibration failed issue, can we use do_reset function to cover it?

    I would recommend to fix your HW malfunction, thus this "IODELAY: Isolation of Device IOs failed" to not occur at all.

    On DRA7x/AM57x, in addition to the regular muxing of pins, an additional hardware module called IODelay which is also expected to be configured. 
    This "IODelay" module has it's own register space that is independent of the control module. It is advocated strongly in TI's official documentation considering the existing design of the DRA7 family of processors during mux or IODelay recalibration,
    there is a potential for a significant glitch which may cause functional impairment to certain hardware. It is hence recommended to do muxing as part of
    IOdelay recalibration. IODELAY recalibration sequence: - Complete AVS voltage change on VDD_CORE_L - Unlock IODLAY config registers. - Perform IO delay calibration with predefined values. - Isolate all the IOs - Update the delay mechanism for each IO with new calibrated values. - Configure PAD configuration registers - De-isolate all the IOs. - Relock IODELAY config registers.


    Refer to below pointers for more info regarding IODELAY:

    http://www.ti.com/lit/an/sprac44a/sprac44a.pdf

    http://www.ti.com/lit/an/sprack1/sprack1.pdf


    You can also check below guides for AM57x HW check and diagnostic.

    http://www.ti.com/lit/an/sprack7b/sprack7b.pdf

    http://www.ti.com/lit/an/spraca4/spraca4.pdf

    http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_faq.html#diagnostics

    http://software-dl.ti.com/processor-sdk-rtos/esd/docs/latest/rtos/index_board.html#diagnostics

    Regards,
    Pavel