/*
* 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
/******************************************************************************/
extern void uart_early_init(void);
extern void uart_early_puts(const char *ss);
extern void reset_cpu(unsigned long addr);
extern void mmu_pagedir_init(unsigned long);
extern void mmu_pagedir_cached_range(unsigned long,
unsigned long, unsigned long);
extern void mmu_startup(unsigned long);
extern void dcache_flush_all(void);
extern void dcache_inv_all(void);
extern void mmu_turnoff(void);
/******************************************************************************/
const uintptr_t IMAGE_ENTRY = (CONFIG_SYS_TEXT_BASE);
extern unsigned char input_data[];
extern unsigned char input_data_end[];
extern unsigned long _start;
/******************************************************************************/
#define error(_s) uart_early_puts(_s)
#define putstr(_s) uart_early_puts(_s)
#define large_malloc(_n) malloc(_n)
#define large_free(_n) free(_n)
/******************************************************************************/
/*
* this value will be (_start - CONFIG_SYS_MALLOC_LEN)
*/
static long malloc_start_lzma;
/******************************************************************************/
static void *malloc(unsigned int size)
{
void *ptr = (void *)malloc_start_lzma;
malloc_start_lzma += size;
if (malloc_start_lzma >= (unsigned long)&_start)
return NULL;
return ptr;
}
/******************************************************************************/
static void free(void *ptr)
{
}
/******************************************************************************/
#include "unlzma.c"
#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_EARLY_DCACHE_ENABLE
static int early_dcache_enable(void)
{
unsigned long pdt = CONFIG_SYS_SDRAM_BASE + SZ_64K;
mmu_pagedir_init(pdt);
mmu_pagedir_cached_range(pdt, CONFIG_SYS_SDRAM_BASE, SZ_256M);
mmu_startup(pdt);
return 0;
}
static int early_dcache_disable(void)
{
int i = 0;
dcache_flush_all();
/* mem barrier to sync up things */
asm("mcr p15, 0, %0, c7, c10, 4" : : "r"(i));
dcache_inv_all();
mmu_turnoff();
return 0;
}
#endif
/******************************************************************************/
void start_armboot(void)
{
unsigned char *pdst = (unsigned char *)IMAGE_ENTRY;
unsigned int image_data_len = input_data_end - input_data;
malloc_start_lzma = ((uintptr_t)&_start - CONFIG_SYS_MALLOC_LEN);
uart_early_init();
if (input_data[0] == 0x5D) {
uart_early_puts("\nUncompress");
//early_dcache_enable();
decompress(input_data, image_data_len, pdst);
//early_dcache_disable();
uart_early_puts("Ok\r\n");
} else {
int *s = (int *)input_data;
int *d = (int *)pdst;
unsigned int len = ((image_data_len + 3) >> 2);
while (len--)
*d++ = *s++;
}
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);
}