/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/


#include "x_typedef.h"
#include "x_pdwnc.h"
#include "x_ckgen.h"
#include "x_bim.h"
#include "x_lint.h"
#include "x_assert.h"
#include "x_printf.h"
#include "x_hal_5381.h"
#include "x_dram.h"
#include "chip_txt.h"
#include <string.h>

#ifdef CC_MTK_LOADER
#define LOG(level, fmt...)   Printf(fmt)
#endif
//-----------------------------------------------------------------------------
// Extern functions declaration
//-----------------------------------------------------------------------------
EXTERN INT32 Printf(const CHAR *format, ...);
EXTERN void RemapJumpToDram(void);
#ifdef CC_UBOOT
EXTERN void *x_memcpy(void *, const void *, UINT32);
#else
EXTERN void *x_memcpy(void *, const void *, SIZE_T);
#endif

//lint --e{961} Violates MISRA Advisory Rule 28, 'register' class
//lint --e{950} No ANSI reserved word (__asm)
//lint --e{529} Symbol not subsequently referenced
//lint --e{506} Constant value Boolean
//lint --e{774} Boolean within 'if' always evaluates to constant
//lint --e{775} non-negative quantity cannot be less than zero
LINT_SUPPRESS_SYMBOL(18, Printf)

#ifdef CC_MTK_PRELOADER
#define Printf(fmt...)
#endif /* CC_MTK_PRELOADER */

//lint --e{77}
LINT_SAVE_AND_DISABLE

#if !defined(__GCC__)
EXTERN UINT32 Image$$BSS$$Limit;
#else /*__GCC__*/
EXTERN UINT32 __bss_end;
#endif /*__GCC__*/

LINT_RESTORE

extern void RemapJumpToDram(void);

extern void CHIP_Reboot(void);

void CLK_Shadow()
{
    UINT32 fgNotEqual=0;
#ifndef CC_MT5863//no need to copy preloader to dram again  for crax
    UINT32 *pu4Nor, *pu4Mem;
#ifdef __GCC__
    UINT32 u4BSSLimit = (UINT32)&__bss_end;
#else
    UINT32 u4BSSLimit = (UINT32)&Image$$BSS$$Limit;
#endif
    LINT_SAVE_AND_DISABLE
    #if defined(CC_NAND_BOOT) || defined(CC_EMMC_BOOT)
	    #if defined(CC_MT5883)&&defined(CC_NOR2NAND_BOOT)
		    x_memcpy((void *)INIT_DRAM_B_BASE, (void *)0, 0xA000);
		#else
            x_memcpy((void *)INIT_DRAM_B_BASE, (void *)SRAM_START, u4BSSLimit - SRAM_START );
		#endif
    #else
        x_memcpy((void *)INIT_DRAM_B_BASE, (void *)0, u4BSSLimit);
    #endif
    LINT_RESTORE


//to support secure NOR boot could be compatitible with normal NOR boot
#if defined(CC_NAND_BOOT) || defined(CC_EMMC_BOOT)
    #if defined(CC_MT5883)&&defined(CC_NOR2NAND_BOOT)
	    pu4Nor = (UINT32 *)0;
	#else
        pu4Nor = (UINT32 *)SRAM_START;
	#endif
#else
    pu4Nor = (UINT32 *)0;
#endif
    pu4Mem = (UINT32 *)INIT_DRAM_B_BASE;

    fgNotEqual = 0;
    LINT_SAVE_AND_DISABLE
#if defined(CC_MT5883)&&defined(CC_NOR2NAND_BOOT)
    while ((fgNotEqual < 20) && ((UINT32)pu4Nor < 0x8000))
#else
    while ((fgNotEqual < 20) && ((UINT32)pu4Nor < u4BSSLimit))
#endif
    LINT_RESTORE
    {
        if ((*pu4Nor) != (*pu4Mem))
        {
            fgNotEqual++;
			#ifdef CC_MTK_LOADER
            LOG(0,"0x%08x: Nor-0x%08x Mem-0x%08x\n", (UINT32)pu4Nor, *pu4Nor, *pu4Mem);
			#endif
        }
        pu4Nor++;
        pu4Mem++;
    }
#endif

    if (!fgNotEqual)
    {
#ifdef CC_ROM_BOOT
        BIM_WRITE32(4, BROM_BASE);
#endif /* CC_ROM_BOOT */
        RemapJumpToDram();
    }

    // TODO:fill the default monitor value
    //BIM_WRITE32(REG_RW_DBG_MONSEL, 0x6005e);

#ifdef NDEBUG
    // reboot in release mode if dram initialized failed.
    CHIP_Reboot();
#endif /* NDEBUG */


}
