/*
 * bsp.c
 *
 *  Created on: Feb 9, 2012
 *      Author: TongXiangbiao
 */

#include "bsp.h"
#include "rt.h"
#ifdef __LIGHT_DIFF_ACT_PRO__ // sunxi 20190904 光差保护
#include "fec.h"	// sunxi 20190904 added
#endif // __LIGHT_DIFF_ACT_PRO__
int g_con_uart_index;

/*------------------------------ 类型结构 -------------------------------------
*/


/*------------------------------ 全局变量 -------------------------------------
*/
const char * szTool = "JHW GH-F308 1.00.01";

struct init_t  g_bsp_init_func[]=
{
	{ccu_init,ERR_CODE_INIT_SOFTWARE},	//初始化系统时钟CCU
	{bsp_ustimer_init,ERR_CODE_INIT_SOFTWARE},	//初始化内核USTIMER
	{ustimer_init,ERR_CODE_INIT_SOFTWARE},	//初始化USTIMER
	{gps_init,ERR_CODE_INIT_SOFTWARE},		//初始化GPS
	{pps_init,ERR_CODE_INIT_SOFTWARE},		//初始化PPS
	// {shm_init,ERR_CODE_INIT_SOFTWARE},	//初始化shm
	// {mb_init,ERR_CODE_INIT_SOFTWARE},	//初始化mb
	{watchdog_init,ERR_CODE_INIT_SOFTWARE},	//初始化watchdog
	{gpio_init,ERR_CODE_INIT_SOFTWARE},		//初始化GPIO
	{i2c_init,ERR_CODE_INIT_SOFTWARE},		//初始化I2C模块
	{rtc_init,ERR_CODE_INIT_SOFTWARE},		//初始化RTC模块
	{dspi_init,ERR_CODE_INIT_SOFTWARE},		//初始化DSPI模块
	{log_init,ERR_CODE_LOG},				//日志初始化需要上电时间，放在RTC初始化后
//	{adc_init,ERR_CODE_INIT_SOFTWARE},		//初始化ADC模块,需要根据配置设置ADC输入范围，移至通道配置后
//	{freq_init,ERR_CODE_INIT_SOFTWARE},		//初始化频率测量模块 -------- noted by sunxi 移到裸核上
//	{mac_init,ERR_CODE_INIT_SOFTWARE},		//初始化MAC模块
	{e2prom_init,ERR_CODE_INIT_E2PROM},		//初始化E2PROM模块
#ifdef BSP_CAN_ENABLE
	{can_init,ERR_CODE_INIT_SOFTWARE},		//初始化CAN模块
	{can_app_init,ERR_CODE_INIT_SOFTWARE},	//初始化CAN_APP模块	
#endif
#ifdef TMP_CHIP_AHT20
	{aht20_init,ERR_CODE_INIT_SOFTWARE},	//初始化温湿度传感器 TODO增加初始化错误代码
#endif
//	{uart_init,ERR_CODE_INIT_SOFTWARE},		//初始化UART模块,无需集中初始化，使用时再初始化，防止和通讯子站软件冲突
//	{pit_init,ERR_CODE_UNKOWN}				//初始化PIT(可编程中断定时器)
#ifdef __LIGHT_DIFF_ACT_PRO__ // sunxi 20190904 光差保护
	{fec2_reinit,ERR_CODE_NUM-1},				// sunxi 20190904 added
#endif // __LIGHT_DIFF_ACT_PRO__
};
#define BSP_INIT_NUM	((int)(sizeof(g_bsp_init_func)/sizeof(g_bsp_init_func[0])))

INIT_FUNC g_bsp_exit_func[]=
{
	// 关闭打开的文件
#ifdef __LIGHT_DIFF_ACT_PRO__ // sunxi 20190908 光差保护
	fec2_exit,	// sunxi 20190904 added
#endif // __LIGHT_DIFF_ACT_PRO__
//	flash_exit,
	e2prom_exit,
	
	//关闭bsp中打开的中断
//	pit_exit,
#ifdef BSP_CAN_ENABLE
	can_app_exit,
	can_exit,
#endif
#ifdef TMP_CHIP_AHT20
	aht20_exit,
#endif
//	freq_exit,
//	adc_exit,
	gpio_exit,
	watchdog_exit,
	shm_exit,
	mb_exit,
	ustimer_exit,
	bsp_ustimer_exit,
	gps_exit,
	log_exit,
	ccu_exit,
};
#define BSP_EXIT_NUM	(sizeof(g_bsp_exit_func)/sizeof(g_bsp_exit_func[0]))

unsigned long g_cpu_clk;
int get_clocks(void);

int bsp_init(void)
{
	int i,ret;
	
	//得到CPU主时钟频率
	get_clocks();

	for(i=0;i<BSP_INIT_NUM;i++)
	{
		ret = g_bsp_init_func[i].func();
		if(ret != 0)
		{
			rt_err_set(g_bsp_init_func[i].err_code,0);
			rt_printf("bsp_init err(i=%d,ret=%d)\r\n",i,ret);
		}
	}
	
	return 0;
}


int bsp_exit(void)
{
	int i,ret;

	for(i=0;i<(int)(BSP_EXIT_NUM);i++)
	{
		ret = g_bsp_exit_func[i]();
		if(ret != 0)
		{
			rt_printf("bsp_exit err(i=%d,ret=%d)\r\n",i,ret);
		}
	}

	return 0;
}


#define MCF_CCM_CCR_PLLMULT_MASK	0X03
#define MCF_CLOCK_PCR_OUTDIV_MASK	0x1F	
#define CCM_MISCCR2_FBHALF		    0x02
#define PLL_CR_FBKDIV_BITS			0x3f

#define MCF_CLOCK_PCR               (*(unsigned int*)(0xFC0C0000))
#define MCF_CLOCK_PDR               (*(unsigned int*)(0xFC0C0004))

int get_clocks(void)
{
#if 0
	//int pllmult_nopci[] = {10, 15, 16, 20};
	unsigned long  inp_clk,vco_clk,cpu_clk,bus_clk,flb_clk,ddr_clk,temp;

	inp_clk = CFG_EXT_OSC_CLK;	// Input clock
	//vco_clk = pllmult_nopci[(MCF_CCM_CCR >> 6) & MCF_CCM_CCR_PLLMULT_MASK] * inp_clk;
	vco_clk = ((MCF_CLOCK_PCR & PLL_CR_FBKDIV_BITS) + 1) * inp_clk;

	temp = ((MCF_CLOCK_PDR >> 0) & MCF_CLOCK_PCR_OUTDIV_MASK) + 1;
	cpu_clk = vco_clk / temp;	//cpu clock

	temp = ((MCF_CLOCK_PDR >> 5) & MCF_CLOCK_PCR_OUTDIV_MASK) + 1;
	flb_clk = bus_clk = vco_clk / temp;	// flb & bus clock

	if(MCF_CCM_MISCCR2 & CCM_MISCCR2_FBHALF)
	{
		flb_clk >>= 1;	// FlexBus clock half
	}

	ddr_clk = cpu_clk;	
	if(!(MCF_CCM_MISCCR2 & MCF_CCM_MISCCR2_DDR2CLK))
	{
		ddr_clk >>= 1;	
	}
	
	//初始化全局CPU主时钟频率
	g_cpu_clk = cpu_clk;

#endif
	return 0;
}

	

int get_clocks_printf(void)
{
#if 0
	//int pllmult_nopci[] = {10, 15, 16, 20};
	unsigned long  inp_clk,vco_clk,cpu_clk,bus_clk,flb_clk,ddr_clk,temp;

	inp_clk = CFG_EXT_OSC_CLK;	// Input clock
	//vco_clk = pllmult_nopci[(MCF_CCM_CCR >> 6) & MCF_CCM_CCR_PLLMULT_MASK] * inp_clk;
	vco_clk = ((MCF_CLOCK_PCR & PLL_CR_FBKDIV_BITS) + 1) * inp_clk;

	temp = ((MCF_CLOCK_PDR >> 0) & MCF_CLOCK_PCR_OUTDIV_MASK) + 1;
	cpu_clk = vco_clk / temp;	//cpu clock

	temp = ((MCF_CLOCK_PDR >> 5) & MCF_CLOCK_PCR_OUTDIV_MASK) + 1;
	flb_clk = bus_clk = vco_clk / temp;	// flb & bus clock

	if(MCF_CCM_MISCCR2 & CCM_MISCCR2_FBHALF)
	{
		flb_clk >>= 1;	// FlexBus clock half
	}

	ddr_clk = cpu_clk;	
	if(!(MCF_CCM_MISCCR2 & MCF_CCM_MISCCR2_DDR2CLK))
	{
		ddr_clk >>= 1;	
	}
	
	rt_printf("inp_clk=%ldMHZ,vco_clk=%ldMHZ,cpu_clk=%ldMHZ\r\n",inp_clk/1000000,vco_clk/1000000,cpu_clk/1000000);
	rt_printf("bus_clk=%ldMHZ,flb_clk=%ldMHZ,ddr_clk=%ldMHZ\r\n",bus_clk/1000000,flb_clk/1000000,ddr_clk/1000000);
#endif	
	return 0;
}

char * q16_to_str(long q16)
{
	static char str[32];

#if 1
	sprintf(str,"%f",(float)q16/Q16_BASE);
#else
	str[0] = 0;
	
	if(q16<0) 
	{
		q16 = -q16;
		sprintf(str,"-");
	}
     
	sprintf(str+strlen(str),"%d.%04d",q16>>16,(q16&0xffff)*10000/0x10000);
#endif
	return str;
}



