/*
 * Copyright (c) 2012-2019 Andes Technology Corporation
 * All rights reserved.
 * Modified for SpaceTouch Orange SoC project by Qi Zhang
 * 2020/12/16: First commit
 */

#include "platform.h"
#include "brom_func.h"
#include "quad_flash.h"

__GLOBAL SOC_RUNTIME RUNTIME_SPV40 = { 0 };

void system_init(void) {
	/* Enable PLIC features */
	__nds__plic_set_feature(NDS_PLIC_FEATURE_VECTORED|NDS_PLIC_FEATURE_PREEMPT);
	HAL_MEIP_ENABLE();
	for(int i=1;i<=NUM_OF_IRQ;i++)
	{
		HAL_INTERRUPT_ENABLE(i);
	}
}

void c_startup(void) {

	/* Data section initialization */
	extern int8_t __bss_start, __bss_end;
	extern int8_t __ilm_lmastart, __ilm_start, __ilm_end;
	extern int8_t __dlm_lmastart, __dlm_start, __dlm_end;
	extern int8_t __iram_lmastart, __iram_start, __iram_end;
	extern int8_t __dram_lmastart, __dram_start, __dram_end;
	uint32_t size;

	/* Copy .ilm section to ILM */
	if ((&__ilm_start) != (&__ilm_lmastart)) {
		size = &__ilm_end - &__ilm_start;
		brom_memcpy(&__ilm_start, &__ilm_lmastart, size);
	}

	/* Copy PLIC vector table and other assigned data sections to DLM */
	if ((&__dlm_start) != (&__dlm_lmastart)) {
		size = &__dlm_end - &__dlm_start;
		brom_memcpy(&__dlm_start, &__dlm_lmastart, size);
	}

	if ((&__iram_start) != (&__iram_lmastart)) {
		size = &__iram_end - &__iram_start;
		/* 0x20000000 is the mandatory offset to maintain cache consistency. DO NOT MODIFY. */
		brom_memcpy(&__iram_start + 0x20000000, &__iram_lmastart, size);
	}

	if ((&__dram_start) != (&__dram_lmastart)) {
		size = &__dram_end - &__dram_start;
		brom_memcpy(&__dram_start, &__dram_lmastart, size);
	}

	/* Clear .bss section */
	size = &__bss_end - &__bss_start;
	brom_memset(&__bss_start, 0, size);

	__nds__fencei();
}

__OS1 __INIT void once_loader(void) {
	uint32_t tag_magic = *((volatile uint32_t *)0x4c000004);
	if(tag_magic == 0x40565053)	//get flash
	{
		uint32_t user_flag = *((volatile uint32_t *)0x4c00000c);
		uint32_t flash_data_width = 1;

		if((user_flag & USER_FLAG_FLASH_DATA_WIDTH) == (1u << 6))
		{
			flash_data_width = 2;
		}
		else if((user_flag & USER_FLAG_FLASH_DATA_WIDTH) == (2u << 6))
		{
			flash_data_width = 4;
		}

		uint32_t flash_type = user_flag & USER_FLAG_FLASH_TYPE ? 1: 0;

		extern uint32_t __switch_lmastart, __switch_size;
		void (*func)(uint32_t,uint32_t,uint32_t,uint32_t);
		if((uint32_t)&__switch_lmastart >= 0x10000)
		{
			brom_memcpy((void*)0,&__switch_lmastart,(uint32_t)&__switch_size);
			func = (void (*)(uint32_t,uint32_t,uint32_t,uint32_t))0;
		}
		else
		{
			func = (void (*)(uint32_t,uint32_t,uint32_t,uint32_t))&__switch_lmastart;
		}
		func(DEV_RMU->BOOT_f.BOOT_SEL,flash_type,24000000,flash_data_width);
	}
	extern void routine(void);
	routine();
}


