/*
* startup.c
*
* This file is used to initialize the board hardware.
*
* Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* 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 the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
#include
#include
#include
#include
/******************************************************************************/
const uintptr_t image_entry = (CONFIG_SYS_TEXT_BASE);
/******************************************************************************/
#define error(_s) uart_early_puts(_s)
#define putstr(_s) uart_early_puts(_s)
#include "hw_decompress.c"
#define GZIP_SIZE_OFFSET 0x4
#ifndef CONFIG_SYS_ICACHE_OFF
/* Invalidate entire I-cache and branch predictor array */
static void invalidate_icache_all(void)
{
/*
* Invalidate all instruction caches to PoU.
* Also flushes branch target cache.
*/
asm volatile("mcr p15, 0, %0, c7, c5, 0" : : "r"(0));
/* Invalidate entire branch predictor array */
asm volatile("mcr p15, 0, %0, c7, c5, 6" : : "r"(0));
/* Full system DSB - make sure that the invalidation is complete */
dsb();
/* ISB - make sure the instruction stream sees it */
isb();
}
#else
static void invalidate_icache_all(void)
{
}
#endif
#ifdef CONFIG_MINI_BOOT
#ifndef bit
#define bit(x) (1 << (x))
#endif
#define TIME2_CLK_SEL bit(18)
int timer_init(void)
{
/*
* Under uboot, 0xffffffff is set to load register,
* timer_clk equals BUSCLK/2/256.
* e.g. BUSCLK equals 50M, it will roll back after 0xffffffff/timer_clk
* 43980s equals 12hours
*/
__raw_writel(0, CFG_TIMERBASE + REG_TIMER_CONTROL);
__raw_writel(~0, CFG_TIMERBASE + REG_TIMER_RELOAD);
/* 32 bit, periodic */
__raw_writel(CFG_TIMER_CTRL, CFG_TIMERBASE + REG_TIMER_CONTROL);
/* start timer2 with mode below */
unsigned int reg;
reg = __raw_readl(SYS_CTRL_REG_BASE + REG_SC_CTRL);
/* for timer2,use sys BUS clk */
reg |= TIME2_CLK_SEL;
__raw_writel(reg, SYS_CTRL_REG_BASE + REG_SC_CTRL);
/* disable timer2 */
__raw_writel(0, TIMER2_REG_BASE + REG_TIMER_CONTROL);
/* timer2 load */
__raw_writel(~0, TIMER2_REG_BASE + REG_TIMER_RELOAD);
/*
* Timing mode: 32bits [bit 1 set as 1]
* ticking with 1/256 clock frequency [bit 3 set as 1, bit 2 set as 0]
* timing circulary [bit 6 set as 1]
* timer enabled [bit 7 set as 1]
*/
reg = (1 << 7) | (1 << 6) | (1 << 3) | (1 << 1);
__raw_writel(reg, TIMER2_REG_BASE + REG_TIMER_CONTROL);
return 0;
}
#define TIME_STAMP_CNT 0x12020138
#define TIME_STAMP_VALUE 0x04010050
#define CONFIG_TIME_STAMP_ENABLE
void time_stamp(const char *strfunc, int nline, int type)
{
#ifdef CONFIG_TIME_STAMP_ENABLE
static int init_flag = 0;
unsigned int cnt;
unsigned int stamp;
unsigned int *addr = NULL;
if (!init_flag) {
init_flag = 1;
*(unsigned int *)TIME_STAMP_CNT = 0;
}
cnt = *(unsigned int *)TIME_STAMP_CNT;
stamp = *(unsigned int *)(TIMER2_REG_BASE + REG_TIMER_VALUE);
addr = (unsigned int *)(TIME_STAMP_VALUE + cnt * 16); /* 16:The number in the formula */
*addr = ~stamp;
addr++;
*addr = (uintptr_t)strfunc;
addr++;
*addr = nline;
addr++;
*addr = type;
cnt++;
*(unsigned int *)TIME_STAMP_CNT = cnt;
#endif
}
#endif
/******************************************************************************/
void start_armboot(void)
{
unsigned char *pdst_l32 = NULL;
unsigned int image_data_len;
int pdst_len;
int ret;
int i;
char *p = NULL;
char *q = NULL;
#ifndef CONFIG_MINI_BOOT
uart_early_init();
uart_early_puts("\r\nUncompress ");
#endif
/* use direct address mode */
hw_dec_type = 0;
/* init hw decompress IP */
hw_dec_init();
/* start decompress */
pdst_l32 = (unsigned char *)(uintptr_t)image_entry;
image_data_len = input_data_end - input_data;
/* get dets length from compress image */
p = (char *)&pdst_len;
q = (char *)(input_data_end - GZIP_SIZE_OFFSET);
for (i = 0; i < sizeof(int); i++)
p[i] = q[i];
ret = hw_dec_decompress(pdst_l32, &pdst_len, input_data, image_data_len, NULL);
if (!ret) {
#ifndef CONFIG_MINI_BOOT
uart_early_puts("Ok!");
#endif
} else {
#ifndef CONFIG_MINI_BOOT
uart_early_puts("Fail!");
#endif
while (1);
}
/* uinit hw decompress IP */
hw_dec_uinit();
void (*uboot)(void);
uboot = (void (*))CONFIG_SYS_TEXT_BASE;
invalidate_icache_all();
uboot();
}
/******************************************************************************/
void hang(void)
{
uart_early_puts("### ERROR ### Please RESET the board ###\n");
for (;;) ;
}
void do_bad_sync(void)
{
uart_early_puts("bad sync abort\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}
void do_sync(void)
{
uart_early_puts("sync abort\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}
void do_bad_error(void)
{
uart_early_puts("bad error\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}
void do_error(void)
{
uart_early_puts("error\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}
void do_bad_fiq(void)
{
uart_early_puts("bad fast interrupt request\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}
void do_bad_irq(void)
{
uart_early_puts("bad interrupt request\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}
void do_fiq(void)
{
uart_early_puts("fast interrupt request\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}
void do_irq(void)
{
uart_early_puts("interrupt request\r\n");
uart_early_puts("Resetting CPU ...\r\n");
reset_cpu(0);
}